package com.corpgovernment.travelstandard.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.lang.Tuple;
import cn.hutool.core.util.BooleanUtil;
import cn.hutool.core.util.ObjectUtil;
import com.corpgovernment.api.applytrip.apply.sync.StandardAmountSyncRequest;
import com.corpgovernment.api.applytrip.soa.response.QueryApplyTripStandardResponse;
import com.corpgovernment.api.basic.request.CityInfoQuickDisplayRequest;
import com.corpgovernment.api.basic.response.CityInfoQuickDisplayResponse;
import com.corpgovernment.api.basic.vo.CityBasicInfoVO;
import com.corpgovernment.api.basic.vo.ProvinceInfoVO;
import com.corpgovernment.api.organization.model.post.PostVo;
import com.corpgovernment.api.supplier.soa.constant.ProductTypeEnum;
import com.corpgovernment.api.travelstandard.enums.*;
import com.corpgovernment.api.travelstandard.service.IMbTravelstandHotelService;
import com.corpgovernment.api.travelstandard.vo.*;
import com.corpgovernment.api.travelstandard.vo.operate.HotelOperateLogVo;
import com.corpgovernment.api.travelstandard.vo.request.ExecuteHotelTravelStandardRequest;
import com.corpgovernment.api.travelstandard.vo.request.GetHotelDetailRequest;
import com.corpgovernment.api.travelstandard.vo.response.ExecuteHotelTravelStandardSoaResponse;
import com.corpgovernment.basicdata.bo.HotelCityBo;
import com.corpgovernment.basicdata.service.impl.HotelCityDataService;
import com.corpgovernment.common.apollo.BasicManageApollo;
import com.corpgovernment.common.apollo.CommonApollo;
import com.corpgovernment.common.base.BaseUserInfo;
import com.corpgovernment.common.base.JSONResult;
import com.corpgovernment.common.base.Page;
import com.corpgovernment.common.common.CorpBusinessException;
import com.corpgovernment.common.currency.bo.CurrencyExchangeBO;
import com.corpgovernment.common.enums.ExceptionCodeEnum;

import com.corpgovernment.common.mq.enums.MessageBizTypeEnum;
import com.corpgovernment.common.tuple.Tuple2;
import com.corpgovernment.common.utils.*;
import com.corpgovernment.organization.Bo.SyncEmployeeInfoBo;
import com.corpgovernment.organization.check.DateRange;
import com.corpgovernment.organization.constant.OrganizationResponseCodeEnum;
import com.corpgovernment.organization.constant.SyncImportExcelConst;
import com.corpgovernment.organization.dataloader.ApplyTripClientLoader;
import com.corpgovernment.organization.dataloader.BasicDataClientLoader;
import com.corpgovernment.organization.dataloader.BasicOssClientLoader;
import com.corpgovernment.organization.entity.SyncEmployeeCallBackRequestEntity;
import com.corpgovernment.organization.entity.SyncOrganizationRequestEntity;
import com.corpgovernment.organization.entity.db.MbImportExcelRecord;
import com.corpgovernment.organization.entity.db.MbOrgInfo;
import com.corpgovernment.organization.enumm.ExcelPostEnum;
import com.corpgovernment.organization.enumm.FileTemplateEnum;
import com.corpgovernment.organization.service.IOrganizationInfoService;
import com.corpgovernment.organization.service.IPostService;
import com.corpgovernment.organization.util.ExcelUtils;
import com.corpgovernment.organization.util.StrUtils;
import com.corpgovernment.organization.vo.ExcelCreateVO;
import com.corpgovernment.travelstandard.constant.ServiceConstant;
import com.corpgovernment.travelstandard.convert.HotelStandardConvert;
import com.corpgovernment.travelstandard.entity.db.*;
import com.corpgovernment.travelstandard.enums.*;
import com.corpgovernment.travelstandard.mapper.*;
import com.corpgovernment.travelstandard.utils.BeanConverUtil;
import com.corpgovernment.travelstandard.vo.*;
import com.ctrip.corp.obt.generic.core.context.UserInfoContext;
import com.ctrip.corp.obt.generic.utils.CollectionUtils;
import com.ctrip.corp.obt.generic.utils.DateUtils;
import com.ctrip.corp.obt.generic.utils.JsonUtils;
import com.ctrip.corp.obt.generic.utils.StringUtils;
import com.ctrip.corp.obt.shard.context.PageContext;
import com.excel.service.excel.*;
import com.excel.util.TransactionUtils;
import com.ctrip.vul.VulDef;
import com.ctrip.vul.VulDef;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.BooleanUtils;
import org.apache.commons.lang3.math.NumberUtils;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xssf.usermodel.XSSFRow;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;
import tk.mybatis.mapper.entity.Example;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.net.HttpURLConnection;
import java.net.InetSocketAddress;
import java.net.Proxy;
import java.net.URL;
import java.security.SecureRandom;
import java.util.*;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

import static com.corpgovernment.organization.check.DateRangeOverlapChecker.hasOverlap;
import static com.corpgovernment.organization.check.DateRangeOverlapChecker.makeDate;
import static com.corpgovernment.organization.dataloader.BasicDataClientLoader.*;
import static com.ctrip.corp.obt.generic.utils.DateUtils.DATE_FORMAT;


@Slf4j
@Service
public class MbTravelstandHotelService extends TravelStandardBaseService implements IMbTravelstandHotelService {

    private final static String[] HOTEL_RC_TEMPS = {"hotelRcHpTemp"};

    private final static String[] STAR_NAMES = {"不限", "一星级", "二星级", "三星级", "四星级", "五星级", "六星级"};

    @Autowired
    private MbTravelstandHotelMapper mbTravelstandHotelMapper;
    @Autowired
    private MbTravelstandReasonCodeService travelstandReasonCodeService;
    @Autowired
    private TravelStandardPostService travelStandardPostService;
    @Autowired
    private MbTravelstandHotelPriceService travelstandHotelPriceService;
    @Autowired
    private MbTravelstandHotelQuarterService travelstandHotelQuarterService;
    @Autowired
    private AreaConfigService areaConfigService;
    @Autowired
    private CityConfigService cityConfigService;
	@Autowired
	private IPostService postService;
    @Autowired
    private IOrganizationInfoService organizationInfoService;
    @Autowired
    private HotelCityDataService hotelCityDataService;
    @Autowired
    private ApplyTripClientLoader applyTripClientLoader;
    @Autowired
    private MbTravelstandCurrencyExchangeService mbTravelstandCurrencyExchangeService;
    @Autowired
    private ExcelUtils excelUtils;
    @Autowired
    private MbTravelstandHotelQuarterMapper mbTravelstandHotelQuarterMapper;
    @Autowired
    private MbHotelQuarterUploadMapper mbHotelQuarterUploadMapper;
    @Autowired
    private MbHotelAreaConfUploadMapper mbHotelAreaConfUploadMapper;
    @Autowired
    private MbHotelQuarterDetailUploadMapper mbHotelQuarterDetailUploadMapper;
    @Autowired
    private MbUploadErrorLogMapper mbUploadErrorLogMapper;
    @Autowired
    private AreaConfigMapper areaConfigMapper;
    @Autowired
    private CityConfigMapper cityConfigMapper;
    @Autowired
    private BasicDataClientLoader basicDataClientLoader;
    @Autowired
    private BasicOssClientLoader basicOssClientLoader;

    @Autowired
    private MbTravelstandHotelService mbTravelstandHotelService;

    @Autowired
    private MybatisBatchUtils mybatisBatchUtils;

    @Autowired
    @Qualifier(value = "defaultThreadPoolExecutor")
    private ThreadPoolExecutor defaultThreadPoolExecutor;


    @Autowired
    private ExcelImportProcessorFactory factory;
    @Autowired
    private TransactionUtils transactionUtils;

    @Autowired
    private CommonApollo commonApollo;


    @Override
    public void insert(MbTravelstandHotelVo model) {
        mbTravelstandHotelMapper.insertSelective(ObjectUtils.copyProperties(model, MbTravelstandHotel.class));
    }

    @Override
    public int delete(Long id) {
        return mbTravelstandHotelMapper.deleteByPrimaryKey(id);
    }

    @Override
    public int update(MbTravelstandHotelVo model) {
        return mbTravelstandHotelMapper.updateByPrimaryKeySelective(ObjectUtils.copyProperties(model, MbTravelstandHotel.class));
    }

    @Override
    public MbTravelstandHotelVo get(Long id) {
        return ObjectUtils.copyProperties(mbTravelstandHotelMapper.selectByPrimaryKey(id), MbTravelstandHotelVo.class);
    }

    @Override
    public List<MbTravelstandHotelVo> list(MbTravelstandHotelVo model) {
        return ListUtils.copyList(mbTravelstandHotelMapper.list(ObjectUtils.copyProperties(model, MbTravelstandHotel.class)), MbTravelstandHotelVo.class);
    }

    @Override
    public Page page(MbTravelstandHotelVo model) {
        MbTravelstandHotel param = ObjectUtils.copyProperties(model, MbTravelstandHotel.class);
        PageContext.startPage(model.getPageNum(), model.getPageSize());
        List<MbTravelstandHotel> list = mbTravelstandHotelMapper.list(param);
        return PageUtils.optPageBy(list, MbTravelstandHotelVo.class);
    }

    @Transactional(rollbackFor = Exception.class)
    public void insertTravelstandHotel(MbTravelstandHotelVo model) {
        MbTravelstandHotel travelstandHotel = ObjectUtils.copyProperties(model, MbTravelstandHotel.class);
        travelstandHotel.setDatachangeCreatetime(new Date());
        travelstandHotel.setDatachangeLasttime(new Date());
        mbTravelstandHotelMapper.insert(travelstandHotel);
        model.setId(travelstandHotel.getId());
        //从apollo获取价格管控默认RC
        insertTravelstandReasonCode(HOTEL_RC_TEMPS, model.getId());
        //获取该组织下的区域信息
        List<AreaConfigVo> areaConfigVos = areaConfigService.getByOrgIdNotInIds(model.getOrgId(), null);
        if (CollectionUtils.isEmpty(areaConfigVos)) {
            List<AreaVo> areaConfigList = areaConfigService.getAreaConfigList(new AreaConfigVo() {{
                setOrgId(model.getOrgId());
                setStatus(NumberUtils.INTEGER_ONE);
            }});
            //查询历史记录是否有已删除的地区数据，没有则初始化地区、城市数据
            if (CollectionUtils.isEmpty(areaConfigList)) {
                areaConfigService.initAreaData(model.getOrgId());
                areaConfigService.initIntlAreaData(model.getOrgId());
                areaConfigVos = areaConfigService.getByOrgIdNotInIds(model.getOrgId(), null);
            }
        }
        //批量插入区域信息
        for (AreaConfigVo areaConfigVo : areaConfigVos) {
            //插入限价信息
            MbTravelstandHotelPriceVo travelstandHotelPriceVo = new MbTravelstandHotelPriceVo();
            travelstandHotelPriceVo.setPriceUpperLimit(null);
            travelstandHotelPriceVo.setTsHotelAreaId(areaConfigVo.getId());
            travelstandHotelPriceVo.setTsHotelId(model.getId());
            travelstandHotelPriceVo.setStar(0);
            travelstandHotelPriceService.insert(travelstandHotelPriceVo);
            //插入淡旺季信息
            MbTravelstandHotelQuarterVo travelstandHotelQuarterVo = new MbTravelstandHotelQuarterVo();
            travelstandHotelQuarterVo.setTsHotelAreaId(areaConfigVo.getId());
            travelstandHotelQuarterVo.setTsHotelId(model.getId());
            travelstandHotelQuarterService.insert(travelstandHotelQuarterVo);
        }
        insertOperateLog(coverMbTravelstandHotelVoToFlightOperateLogVo(model));
    }

    @Transactional(rollbackFor = Exception.class)
    public JSONResult updateTravelstandHotelProperty(HotelTravelStandardManageVo hotelTravelStandardManageVo) {
        log.info("updateTravelstandHotelProperty request info:{}", JsonUtils.toJsonString(hotelTravelStandardManageVo));
        // 参数校验
        checkRequestParam(hotelTravelStandardManageVo);
        String jobScopeId = hotelTravelStandardManageVo.getJobScopeId();
        if (StringUtils.isBlank(jobScopeId)) {
            throw new CorpBusinessException(OrganizationResponseCodeEnum.JOB_SCOPEID_IS_NULL);
        }
        String orgid = hotelTravelStandardManageVo.getOrgId();
        if (StringUtils.isBlank(orgid)) {
            throw new CorpBusinessException(OrganizationResponseCodeEnum.ORG_ID_NULL);
        }
        String id = hotelTravelStandardManageVo.getId();
        if (StringUtils.isBlank(id)) {
            throw new CorpBusinessException(OrganizationResponseCodeEnum.TRAVEL_STAND_ID_IS_NULL);
        }
        MbTravelstandHotelVo oriMbTravelstandHotelVo = get(Long.valueOf(hotelTravelStandardManageVo.getId()));
        if (oriMbTravelstandHotelVo == null) {
            throw new CorpBusinessException(OrganizationResponseCodeEnum.TRAVEL_STAND_IS_NULL);
        }
        HotelOperateLogVo oriHotelOperateLogVo = coverMbTravelstandHotelVoToFlightOperateLogVo(oriMbTravelstandHotelVo);
        //更新差标
        MbTravelstandHotelVo travelstandHotelVo = new MbTravelstandHotelVo(
                Long.valueOf(id),
                orgid,
                hotelTravelStandardManageVo.getTitle(),
                hotelTravelStandardManageVo.getHotelPriceControl().getStatus(),
                hotelTravelStandardManageVo.getHotelPriceControl().getHotelPriceRcSet(),
                hotelTravelStandardManageVo.getHotelPriceControl().getHotelQuarterControl().getStatus(),
                hotelTravelStandardManageVo.getHotelPriceControl().getIntlStatus(),
                hotelTravelStandardManageVo.getHotelPriceControl().getSharedManageStatus(),
                hotelTravelStandardManageVo.getHotelPriceControl().getHotelManageRules(),
                hotelTravelStandardManageVo.getHotelPriceControl().getSharedPercentage(),
                hotelTravelStandardManageVo.getHotelPriceControl().getPriceFloatSwitch(),
                hotelTravelStandardManageVo.getHotelPriceControl().getFloatQuarterSwitch(),
                hotelTravelStandardManageVo.getHotelPriceControl().getPriceFloatSwitchIntl(),
                hotelTravelStandardManageVo.getHotelPriceControl().getFloatControlType(),
                hotelTravelStandardManageVo.getHotelPriceControl().getHotelManageStrategy()
        );
        travelstandHotelVo.setHotelProductSwitch(hotelTravelStandardManageVo.getHotelProductSwitch());
        travelstandHotelVo.setHotelIntlProductSwitch(hotelTravelStandardManageVo.getHotelIntlProductSwitch());
        log.info("update travelstandHotelVo info:{}", JsonUtils.toJsonString(travelstandHotelVo));
        if (update(travelstandHotelVo) != 1) {
            throw new CorpBusinessException(OrganizationResponseCodeEnum.TRAVEL_STAND_UPDATE_FAILED);
        }

        // MARK: 2019/12/19 此处可能产生性能瓶颈，可优化
        //删除地区限价信息
        travelstandHotelPriceService.deleteByTsId(travelstandHotelVo.getId());
        //循环添加地区限价信息
        List<MbTravelstandHotelPriceVo> travelstandHotelPriceVos = hotelTravelStandardManageVo.getHotelPriceControl().getHotelPrices();
        mybatisBatchUtils.batchUpdateOrInsert(travelstandHotelPriceVos, MbTravelstandHotelPriceMapper.class, (item, mapper) -> mapper.insertSelective(ObjectUtils.copyProperties(item, MbTravelstandHotelPrice.class)));

        // MARK: 2019/12/19 此处可能产生性能瓶颈，可优化
        //删除淡旺季信息
        travelstandHotelQuarterService.deleteByTsId(travelstandHotelVo.getId());
        //循环添加淡旺季信息
        for (HotelQuarterControl.QuarterInfo quarterInfo : hotelTravelStandardManageVo.getHotelPriceControl().getHotelQuarterControl().getQuarterInfos()) {
            List<MbTravelstandHotelQuarterVo> travelstandHotelQuarterVos = quarterInfo.getHotelQuarterVos();

            mybatisBatchUtils.batchUpdateOrInsert(travelstandHotelQuarterVos, MbTravelstandHotelQuarterMapper.class, (item, mapper) -> mapper.insertSelective(ObjectUtils.copyProperties(item, MbTravelstandHotelQuarter.class)));

        }
        //删除旧职位
        travelStandardPostService.deleteByTsidAndTsType(travelstandHotelVo.getId(), TravelStandardTypeEnum.Hotel.getCode());
        //循环添加职位
        String[] jobIds = jobScopeId.split(",");
        List<TravelStandardPostVo> travelStandardPostVoList = new ArrayList<>();
        for (String jobId : jobIds) {
            TravelStandardPostVo travelStandardPostVo = new TravelStandardPostVo();
            travelStandardPostVo.setPostid(Long.valueOf(jobId));
            travelStandardPostVo.setOrgid(orgid);
            travelStandardPostVo.setTsid(travelstandHotelVo.getId());
            travelStandardPostVo.setTstype(TravelStandardTypeEnum.Hotel.getCode());
            travelStandardPostVo.setTsname(travelstandHotelVo.getName());
            travelStandardPostVoList.add(travelStandardPostVo);
        }
        mybatisBatchUtils.batchUpdateOrInsert(travelStandardPostVoList, TravelStandardPostMapper.class, (item, mapper) -> mapper.insertSelective(ObjectUtils.copyProperties(item, TravelStandardPost.class)));

        //更新价格RC
        RCListVo preiceRcListVo = new RCListVo();
        preiceRcListVo.setId(String.valueOf(travelstandHotelVo.getId()));
        preiceRcListVo.setRcList(hotelTravelStandardManageVo.getHotelPriceControl().getHotelPriceRcList());
        preiceRcListVo.setRcType(ReasonCodeTypeEnum.HP.getCode());
        preiceRcListVo.setTsType(TravelStandardTypeEnum.Hotel.getCode());
        travelstandReasonCodeService.updateTravelstandReasonCode(preiceRcListVo);
        updateOperateLog(oriHotelOperateLogVo, coverMbTravelstandHotelVoToFlightOperateLogVo(travelstandHotelVo));
        return JSONResult.ok();
    }

    private void checkRequestParam(HotelTravelStandardManageVo requestParam) {
        if (requestParam == null){
            return;
        }
        if (requestParam.getHotelPriceControl() != null && !CollectionUtils.isEmpty(requestParam.getHotelPriceControl().getHotelPrices())) {
            // 填入的金额不能超过最大值
            requestParam.getHotelPriceControl().getHotelPrices().forEach(item -> {
                if (item == null) {
                    return;
                }
                // 均价上限校验
                if (item.getPriceUpperLimit() != null && item.getPriceUpperLimit().compareTo(new BigDecimal(ServiceConstant.UPPER_LIMIT_PRICE_OF_TRAVEL_STANDARD)) > 0) {
                    throw new CorpBusinessException(OrganizationResponseCodeEnum.UPPER_LIMIT_PRICE_OF_TRAVEL_STANDARD);
                }
            });
        }
    }

    public void updateStandardName(Long id, String title) {
        MbTravelstandHotelVo oriMbTravelstandHotelVo = get(id);
        if (oriMbTravelstandHotelVo == null) {
            throw new CorpBusinessException(OrganizationResponseCodeEnum.TRAVEL_STAND_IS_NULL);
        }
        HotelOperateLogVo oriHotelOperateLogVo = coverMbTravelstandHotelVoToFlightOperateLogVo(oriMbTravelstandHotelVo);
        update(new MbTravelstandHotelVo() {{
            setId(id);
            setName(title);
        }});
        HotelOperateLogVo hotelOperateLogVo = ObjectUtils.copyProperties(oriHotelOperateLogVo, HotelOperateLogVo.class);
        hotelOperateLogVo.setName(title);
        updateOperateLog(oriHotelOperateLogVo, hotelOperateLogVo);
    }


    @Transactional(rollbackFor = Exception.class)
    public JSONResult deleteTravelstandHotel(Long id) {
        MbTravelstandHotelVo oriMbTravelstandHotelVo = get(id);
        if (oriMbTravelstandHotelVo == null) {
            throw new CorpBusinessException(OrganizationResponseCodeEnum.TRAVEL_STAND_IS_NULL);
        }
        HotelOperateLogVo hotelOperateLogVo = coverMbTravelstandHotelVoToFlightOperateLogVo(oriMbTravelstandHotelVo);
        //删除差标
        delete(id);
        //删除岗位
        travelStandardPostService.deleteByTsidAndTsType(id, TravelStandardTypeEnum.Hotel.getCode());
        //删除rc
        travelstandReasonCodeService.deleteByTsIdAndTsType(id, TravelStandardTypeEnum.Hotel.getCode());
        //删除地区限价
        travelstandHotelPriceService.deleteByTsId(id);
        //删除淡旺季
        travelstandHotelQuarterService.deleteByTsId(id);
        deleteOperateLog(hotelOperateLogVo, new HotelOperateLogVo());
        return JSONResult.ok();
    }

    public List<HotelTravelStandardManageVo> listTravelstandHotel(MbTravelstandHotelVo model) {
        List<MbTravelstandHotelVo> travelstandHotelVos = ListUtils.copyList(mbTravelstandHotelMapper.list(ObjectUtils.copyProperties(model, MbTravelstandHotel.class)), MbTravelstandHotelVo.class);
        List<HotelTravelStandardManageVo> hotelTravelStandardManageVos = new ArrayList<>();
        for (MbTravelstandHotelVo travelstandHotelVo : travelstandHotelVos) {
            //获取rc
            List<MbTravelstandReasonCodeVo> reasonCodeVos = travelstandReasonCodeService.list(new MbTravelstandReasonCodeVo() {{
                setTsId(travelstandHotelVo.getId());
                setTsType(TravelStandardTypeEnum.Hotel.getCode());
            }});
            //获取岗位
            List<TravelStandardPost> travelStandardPosts = travelStandardPostService.list(new TravelStandardPostVo() {{
                setTsid(travelstandHotelVo.getId());
                setTstype(TravelStandardTypeEnum.Hotel.getCode());
            }});
            //获取区域限价
            List<MbTravelstandHotelPriceVo> travelstandHotelPriceVos = travelstandHotelPriceService.listAllTravelstandHotelPrice(travelstandHotelVo.getId(), travelstandHotelVo.getOrgId());
            //获取淡旺季信息
            List<MbTravelstandHotelQuarterVo> travelstandHotelQuarterVos = travelstandHotelQuarterService.list(
                    new MbTravelstandHotelQuarterVo().setTsHotelId(travelstandHotelVo.getId())
            );
            hotelTravelStandardManageVos.add(BeanConverUtil.travelstandHotelVoToHotelTravelStandardManageVo(
                    travelstandHotelVo,
                    ListUtils.copyList(travelStandardPosts, TravelStandardPostVo.class),
                    reasonCodeVos,
                    travelstandHotelPriceVos,
                    travelstandHotelQuarterVos
            ));
        }
        return hotelTravelStandardManageVos;
    }

    public HotelTravelStandardShowVo hotelTravelStandardShowSoa(String uid, String orgId) {
        MbTravelstandHotelVo mbTravelstandHotelVo = getMbTravelstandHotelVoByuidAndOrgId(uid, orgId, null);
        if (mbTravelstandHotelVo == null) {
            return null;
        }
        List<MbTravelstandHotelPriceVo> mbTravelstandHotelPriceVos = travelstandHotelPriceService.list(new MbTravelstandHotelPriceVo() {{
            setTsHotelId(mbTravelstandHotelVo.getId());
        }});
        //拼接限价信息
        HotelTravelStandardShowVo hotelTravelStandardShowVo = new HotelTravelStandardShowVo();
        List<HotelTravelStandardShowVo.PolicyRuleVo> policyRuleVos = new ArrayList<>();
        HotelTravelStandardShowVo.PolicyRuleVo policyRuleVo = new HotelTravelStandardShowVo.PolicyRuleVo();
        policyRuleVo.setTitle("酒店限价");
        List<HotelTravelStandardShowVo.PolicyRuleVo.PolicyDetail> policyDetails = new ArrayList<>();
        for (MbTravelstandHotelPriceVo mbTravelstandHotelPriceVo : mbTravelstandHotelPriceVos) {
            HotelTravelStandardShowVo.PolicyRuleVo.PolicyDetail policyDetail = new HotelTravelStandardShowVo.PolicyRuleVo.PolicyDetail();
            policyDetail.setTitle(mbTravelstandHotelPriceVo.getAreaName());
            policyDetail.setContent(mbTravelstandHotelPriceVo.getPriceUpperLimit().setScale(0, RoundingMode.HALF_UP).toString());
            policyDetails.add(policyDetail);
        }
        policyRuleVo.setPolicyDetail(policyDetails);
        policyRuleVos.add(policyRuleVo);
        return hotelTravelStandardShowVo;
    }

    public List<HotelForAppVo> getHotelTravelForApp(String orgId, Long postId, boolean isDomestic) {
        MbTravelstandHotelVo mbTravelstandHotelVo = getMbTravelstandHotelVoByuidAndOrgId(null, orgId, postId);
        log.info("mbTravelstandHotelVo:{}", JsonUtils.toJsonString(mbTravelstandHotelVo));
        List<HotelForAppVo> hotelForAppVos = new ArrayList<>();
        if (mbTravelstandHotelVo == null) {
            //地区限价信息vo
            HotelForAppVo areaPriceHotelForAppVo = new HotelForAppVo();
            List<RcDetailVo> areaPriceHotelForAppVoRcDetailVos = new ArrayList<>();
            //设置价格信息
            RcDetailVo priceRcDetailVo = new RcDetailVo();
            priceRcDetailVo.setTitle("可订价格");
            priceRcDetailVo.setContent("不限");
            areaPriceHotelForAppVoRcDetailVos.add(priceRcDetailVo);
            //设置星级信息
            RcDetailVo starRcDetailVo = new RcDetailVo();
            starRcDetailVo.setTitle("可订星级");
            starRcDetailVo.setContent("不限");
            areaPriceHotelForAppVoRcDetailVos.add(starRcDetailVo);
            areaPriceHotelForAppVo.setRcDetail(areaPriceHotelForAppVoRcDetailVos);
            hotelForAppVos.add(areaPriceHotelForAppVo);
            //管控方式vo
            HotelForAppVo controlHotelForAppVo = new HotelForAppVo();
            List<RcDetailVo> controlHotelForAppVoRcDetailVos = new ArrayList<>();
            //设置管控方式
            RcDetailVo controlRcDetailVo = new RcDetailVo();
            controlRcDetailVo.setTitle("超标管控方式");
            controlRcDetailVo.setContent("不限");
            controlHotelForAppVoRcDetailVos.add(controlRcDetailVo);
            controlHotelForAppVo.setRcDetail(controlHotelForAppVoRcDetailVos);
            hotelForAppVos.add(controlHotelForAppVo);
            return hotelForAppVos;
        }

        Boolean isOpenSwitch = Boolean.TRUE;
        if (isDomestic){
            isOpenSwitch = Objects.equals(HotelSwitchEnum.priceSwitch.E.getCode(), mbTravelstandHotelVo.getPriceSwitch());
        } else {
            isOpenSwitch = Objects.equals(HotelSwitchEnum.priceSwitch.E.getCode(), mbTravelstandHotelVo.getPriceSwitchIntl());
        }

        //限价管控
        if (isOpenSwitch) {
            AreaConfigVo areaConfigVo = new AreaConfigVo();
            areaConfigVo.setOrgId(orgId);
            areaConfigVo.setHotelType(isDomestic ? "0" : "1");
            areaConfigVo.setStatus(0);
            List<AreaConfigVo> areaConfigVoList = areaConfigService.list(areaConfigVo);
            log.info("areaConfigVoList:{}", JsonUtils.toJsonString(areaConfigVoList));

            areaConfigVoList.forEach(item ->{
                List<RcDetailVo> areaPriceHotelForAppVoRcDetailVos = new ArrayList<>();
                MbTravelstandHotelPriceVo travelstandHotelPriceVo = new MbTravelstandHotelPriceVo();
                travelstandHotelPriceVo.setTsHotelId(mbTravelstandHotelVo.getId());
                travelstandHotelPriceVo.setTsHotelAreaId(item.getId());
                List<MbTravelstandHotelPriceVo> priceVoList = travelstandHotelPriceService.list(travelstandHotelPriceVo);
                log.info("priceVoList:{}", JsonUtils.toJsonString(priceVoList));
                if (CollectionUtils.isNotEmpty(priceVoList)){
                    MbTravelstandHotelPriceVo mbTravelstandHotelPriceVo = priceVoList.get(0);
                    HotelForAppVo areaPriceHotelForAppVo = new HotelForAppVo();
                    RcDetailVo priceRcDetailVo = new RcDetailVo();
                    priceRcDetailVo.setTitle(item.getAreaName() + "可订价格");
                    String content2;
                    if (mbTravelstandHotelPriceVo.getPriceUpperLimit() != null) {
                        content2 = "￥" + mbTravelstandHotelPriceVo.getPriceUpperLimit().setScale(0, RoundingMode.HALF_UP).toString() +  "/间夜";
                    } else {
                        content2 = "不限";
                    }
                    priceRcDetailVo.setContent(content2);

                    RcDetailVo starRcDetailVo = new RcDetailVo();
                    starRcDetailVo.setTitle(item.getAreaName() + "可订星级");
                    if (mbTravelstandHotelPriceVo.getStar() == null || mbTravelstandHotelPriceVo.getStar() == 0) {
                        starRcDetailVo.setContent(STAR_NAMES[0]);
                    } else {
                        starRcDetailVo.setContent(STAR_NAMES[mbTravelstandHotelPriceVo.getStar()] + "及以下");
                    }
                    areaPriceHotelForAppVoRcDetailVos.add(priceRcDetailVo);
                    areaPriceHotelForAppVoRcDetailVos.add(starRcDetailVo);
                    areaPriceHotelForAppVo.setRcDetail(areaPriceHotelForAppVoRcDetailVos);
                    areaPriceHotelForAppVo.setTitle(null);
                    hotelForAppVos.add(areaPriceHotelForAppVo);

                    //淡旺季
                    if (HotelSwitchEnum.QuarterSwitch.E.getCode().equals(mbTravelstandHotelVo.getQuarterSwitch())) {
                        HotelForAppVo quarterHotelForAppVo = new HotelForAppVo();
                        quarterHotelForAppVo.setTitle("淡旺季");
                        List<RcDetailVo> quarterHotelForAppVoRcDetailVos = new ArrayList<>();
                        List<MbTravelstandHotelQuarterVo> mbTravelstandHotelQuarterVoList = travelstandHotelQuarterService.list(new MbTravelstandHotelQuarterVo().setTsHotelId(mbTravelstandHotelVo.getId()).setTsHotelAreaId(areaConfigVo.getId()));
                        for (MbTravelstandHotelQuarterVo mbTravelstandHotelQuarterVo : mbTravelstandHotelQuarterVoList) {
                            //如果未设置淡旺季 开始结束时间则   默认不走淡旺季配置
                            if (Objects.isNull(mbTravelstandHotelQuarterVo.getBeginDate()) || Objects.isNull(mbTravelstandHotelQuarterVo.getEndDate())) {
                                continue;
                            }
                            if (mbTravelstandHotelQuarterVo.getBeginDate().getTime() > System.currentTimeMillis() || mbTravelstandHotelQuarterVo.getEndDate().getTime() < System.currentTimeMillis()) {
                                continue;
                            }
                            RcDetailVo quarterPriceRcDetailVo = new RcDetailVo();
                            if (mbTravelstandHotelQuarterVo.getPriceUpperLimit() != null) {
                                quarterPriceRcDetailVo.setTitle("淡旺季"+ item.getAreaName() + "可订价格");
                                quarterPriceRcDetailVo.setContent( "￥" + mbTravelstandHotelQuarterVo.getPriceUpperLimit().setScale(0, RoundingMode.HALF_UP).toString() + "/间夜");
                            } else {
                                quarterPriceRcDetailVo.setTitle("淡旺季"+ item.getAreaName() + "可订价格");
                                quarterPriceRcDetailVo.setContent("不限");
                            }
                            quarterHotelForAppVoRcDetailVos.add(quarterPriceRcDetailVo);
                            RcDetailVo rcDetailVoQuarterTime = new RcDetailVo();
                            if (mbTravelstandHotelQuarterVo.getBeginDate() != null && mbTravelstandHotelQuarterVo.getEndDate() != null) {
                                rcDetailVoQuarterTime.setTitle("淡旺季"+ item.getAreaName() + "起止时间");
                                if(!DateUtil.dateToString(mbTravelstandHotelQuarterVo.getBeginDate(), DateUtil.DF_Y).equals(DateUtil.dateToString(mbTravelstandHotelQuarterVo.getEndDate(), DateUtil.DF_Y))){
                                    rcDetailVoQuarterTime.setContent(DateUtil.dateToString(mbTravelstandHotelQuarterVo.getBeginDate(), DateUtil.DF_MD) + "-次年" + DateUtil.dateToString(mbTravelstandHotelQuarterVo.getEndDate(), DateUtil.DF_MD));
                                }else {
                                    rcDetailVoQuarterTime.setContent(DateUtil.dateToString(mbTravelstandHotelQuarterVo.getBeginDate(), DateUtil.DF_MD) + "-" + DateUtil.dateToString(mbTravelstandHotelQuarterVo.getEndDate(), DateUtil.DF_MD));
                                }
                            } else {
                                rcDetailVoQuarterTime.setTitle("淡旺季"+ item.getAreaName() + "起止时间");
                                rcDetailVoQuarterTime.setContent("不限");
                            }
                            quarterHotelForAppVoRcDetailVos.add(rcDetailVoQuarterTime);
                        }
                        quarterHotelForAppVo.setRcDetail(quarterHotelForAppVoRcDetailVos);
                        hotelForAppVos.add(quarterHotelForAppVo);
                   }
               }
            });

        }else{
            //地区限价信息vo
            HotelForAppVo areaPriceHotelForAppVo = new HotelForAppVo();
            List<RcDetailVo> areaPriceHotelForAppVoRcDetailVos = new ArrayList<>();
            //设置价格信息
            RcDetailVo priceRcDetailVo = new RcDetailVo();
            priceRcDetailVo.setTitle("可订价格");
            priceRcDetailVo.setContent("不限");
            areaPriceHotelForAppVoRcDetailVos.add(priceRcDetailVo);
            //设置星级信息
            RcDetailVo starRcDetailVo = new RcDetailVo();
            starRcDetailVo.setTitle("可订星级");
            starRcDetailVo.setContent("不限");
            areaPriceHotelForAppVoRcDetailVos.add(starRcDetailVo);
            areaPriceHotelForAppVo.setRcDetail(areaPriceHotelForAppVoRcDetailVos);
            hotelForAppVos.add(areaPriceHotelForAppVo);
            //管控方式vo
            HotelForAppVo controlHotelForAppVo = new HotelForAppVo();
            List<RcDetailVo> controlHotelForAppVoRcDetailVos = new ArrayList<>();
            //设置管控方式
            RcDetailVo controlRcDetailVo = new RcDetailVo();
            controlRcDetailVo.setTitle("超标管控方式");
            controlRcDetailVo.setContent("不限");
            controlHotelForAppVoRcDetailVos.add(controlRcDetailVo);
            controlHotelForAppVo.setRcDetail(controlHotelForAppVoRcDetailVos);
            hotelForAppVos.add(controlHotelForAppVo);
        }
        return hotelForAppVos;
    }

    /**
     * 酒店差标管控
     *
     * @param uid
     * @param orgId
     * @param cityCode
     * @return
     */
    public List<HotelForAppVo> getHotelTravelForApp(String uid, String orgId, String cityCode, Long postId, Long trafficId, String productType, Date checkInDate, Date checkOutDate) {
        MbTravelstandHotelVo mbTravelstandHotelVo = getMbTravelstandHotelVoByuidAndOrgId(uid, orgId, postId);
        List<HotelForAppVo> hotelForAppVos = new ArrayList<>();
        // 查询出差申请单中填写的差标
        QueryApplyTripStandardResponse hotelApplyTripStandard = applyTripClientLoader.getFlightApplyTripStandard(trafficId);
        if (Objects.isNull(hotelApplyTripStandard)) {
            throw new CorpBusinessException(OrganizationResponseCodeEnum.TRAVEL_STAND_APPLY_IS_NULL);
        }
        if (BooleanUtils.isTrue(hotelApplyTripStandard.getEnable())) {
            List<RcDetailVo> areaPriceHotelForAppVoRcDetailVos = new ArrayList<>();
            String unLimitedType = hotelApplyTripStandard.getUnLimitedType();
            StandardAmountSyncRequest amount = hotelApplyTripStandard.getStandardAmount();
            //地区限价信息vo
            HotelForAppVo areaPriceHotelForAppVo = new HotelForAppVo();
            //设置地区名称
            RcDetailVo areaRcDetailVo = new RcDetailVo();
            areaRcDetailVo.setTitle("适用城市");
            areaRcDetailVo.setContent("不限");
            areaPriceHotelForAppVoRcDetailVos.add(areaRcDetailVo);
            //设置价格信息
            RcDetailVo priceRcDetailVo = new RcDetailVo();
            priceRcDetailVo.setTitle("可订价格");
            if (TravelUnLimitedTypeEnum.isUnLimitAmount(unLimitedType)) {
                priceRcDetailVo.setContent("不限");
            } else {
                priceRcDetailVo.setContent("¥" + amount.getPriceUpperLimit().toString() + "/间夜");
            }
            areaPriceHotelForAppVoRcDetailVos.add(priceRcDetailVo);
            //设置星级信息
            RcDetailVo starRcDetailVo = new RcDetailVo();
            starRcDetailVo.setTitle("可订星级");
            starRcDetailVo.setContent("不限");
            areaPriceHotelForAppVoRcDetailVos.add(starRcDetailVo);
            areaPriceHotelForAppVo.setRcDetail(areaPriceHotelForAppVoRcDetailVos);
            hotelForAppVos.add(areaPriceHotelForAppVo);
            //管控方式vo
            HotelForAppVo controlHotelForAppVo = new HotelForAppVo();
            List<RcDetailVo> controlHotelForAppVoRcDetailVos = new ArrayList<>();
            //设置管控方式
            RcDetailVo controlRcDetailVo = new RcDetailVo();
            controlRcDetailVo.setTitle("超标管控方式");
            if (StringUtils.isBlank(amount.getControlType())) {
                controlRcDetailVo.setContent("不限");
            } else {
                controlRcDetailVo.setContent(ControlTypeEnum.getEnumByCode(amount.getControlType()).getName());
            }
            controlHotelForAppVoRcDetailVos.add(controlRcDetailVo);
            controlHotelForAppVo.setRcDetail(controlHotelForAppVoRcDetailVos);
            hotelForAppVos.add(controlHotelForAppVo);
            return hotelForAppVos;
        }

        // 处理国内酒店产线开关
        if (ProductTypeEnum.hotel.name().equals(productType) && Objects.nonNull(mbTravelstandHotelVo) && "N".equals(mbTravelstandHotelVo.getHotelProductSwitch())){
            productControlConvert(hotelForAppVos);
            return hotelForAppVos;
        }
        // 处理海外酒店产线开关
        if (ProductTypeEnum.hotelintl.name().equals(productType) && Objects.nonNull(mbTravelstandHotelVo) && "N".equals(mbTravelstandHotelVo.getHotelIntlProductSwitch())){
            productControlConvert(hotelForAppVos);
            return hotelForAppVos;
        }
        // 没传城市直接返回
        log.info("查询出差申请单差标：trafficId={}, cityCode={}", trafficId,cityCode);
        if(trafficId!=null && StringUtils.isBlank(cityCode)){
            log.info("查询出差申请单差标，没有传城市直接返回：trafficId={}, cityCode={}", trafficId,cityCode);
            return hotelForAppVos;
        }
        //判断CityCode是城市还是国家 cityCode=cityId 名字有差异
        if(StringUtils.isBlank(cityCode)) {
            log.info("查询出差申请单差标，没有传城市抛异常：trafficId={}, cityCode={}", trafficId,cityCode);
            throw new CorpBusinessException(OrganizationResponseCodeEnum.HOTEL_CITY_COUNTRY_IS_NULL);
        }
        HotelCityBo hotelCityBo = hotelCityDataService.searchHotelCity(cityCode);
        if(Objects.isNull(hotelCityBo)) {
            throw new CorpBusinessException(OrganizationResponseCodeEnum.HOTEL_CITY_COUNTRY_IS_NULL);
        }
        if (mbTravelstandHotelVo == null) {
            //地区限价信息vo
            HotelForAppVo areaPriceHotelForAppVo = new HotelForAppVo();
            List<RcDetailVo> areaPriceHotelForAppVoRcDetailVos = new ArrayList<>();
            //设置地区名称
            RcDetailVo areaRcDetailVo = new RcDetailVo();
            areaRcDetailVo.setTitle("适用城市");
            areaRcDetailVo.setContent(hotelCityBo.getCityName());
            areaPriceHotelForAppVoRcDetailVos.add(areaRcDetailVo);
            //设置价格信息
            RcDetailVo priceRcDetailVo = new RcDetailVo();
            priceRcDetailVo.setTitle("可订价格");
            priceRcDetailVo.setContent("不限");
            areaPriceHotelForAppVoRcDetailVos.add(priceRcDetailVo);
            //设置星级信息
            RcDetailVo starRcDetailVo = new RcDetailVo();
            starRcDetailVo.setTitle("可订星级");
            starRcDetailVo.setContent("不限");
            areaPriceHotelForAppVoRcDetailVos.add(starRcDetailVo);
            areaPriceHotelForAppVo.setRcDetail(areaPriceHotelForAppVoRcDetailVos);
            hotelForAppVos.add(areaPriceHotelForAppVo);
            //管控方式vo
            HotelForAppVo controlHotelForAppVo = new HotelForAppVo();
            List<RcDetailVo> controlHotelForAppVoRcDetailVos = new ArrayList<>();
            //设置管控方式
            RcDetailVo controlRcDetailVo = new RcDetailVo();
            controlRcDetailVo.setTitle("超标管控方式");
            controlRcDetailVo.setContent("不限");
            controlHotelForAppVoRcDetailVos.add(controlRcDetailVo);
            controlHotelForAppVo.setRcDetail(controlHotelForAppVoRcDetailVos);
            hotelForAppVos.add(controlHotelForAppVo);
            return hotelForAppVos;
        }

        if (StringUtils.isBlank(orgId)){
            orgId = mbTravelstandHotelVo.getOrgId();
        }

        //true 为国内   false 为国际
        Boolean isOpenSwitch = Boolean.TRUE;
        if (Objects.equals("CN", hotelCityBo.getCountryCode())) {
            isOpenSwitch = Objects.equals(HotelSwitchEnum.priceSwitch.E.getCode(), mbTravelstandHotelVo.getPriceSwitch());
        } else {
            isOpenSwitch = Objects.equals(HotelSwitchEnum.priceSwitch.E.getCode(), mbTravelstandHotelVo.getPriceSwitchIntl());
        }
        //限价管控
        if (isOpenSwitch) {
            orgId = getCorpIdByOrgId(orgId);
            log.info("getHotelTravelForApp orgId:{}", orgId);
            List<AreaConfigVo> areaConfigVos = areaConfigService.getByOrgIdAndTsIdAndCityCode(orgId, cityCode, mbTravelstandHotelVo.getId());
            log.info("areaConfigVos:{}", JsonUtils.toJsonString(areaConfigVos));
            Date sDate = checkInDate == null?new Date():checkInDate;
            Date eDate = checkOutDate == null?DateUtils.addDate(sDate, Calendar.DATE, 1):checkOutDate;
            for (AreaConfigVo areaConfigVo : areaConfigVos) {
                MbTravelstandHotelPriceVo mbTravelstandHotelPriceVo = travelstandHotelPriceService.selectOne(new MbTravelstandHotelPriceVo() {{
                    setTsHotelAreaId(areaConfigVo.getId());
                    setTsHotelId(mbTravelstandHotelVo.getId());
                }});
                if (mbTravelstandHotelPriceVo != null) {
                    HotelForAppVo areaPriceHotelForAppVo = new HotelForAppVo();
                    List<RcDetailVo> areaPriceHotelForAppVoRcDetailVos = new ArrayList<>();
                    //设置地区名称
                    RcDetailVo areaRcDetailVo = new RcDetailVo();
                    areaRcDetailVo.setTitle("适用城市");
                    areaRcDetailVo.setContent(hotelCityBo.getCityName());
                    //设置限价信息
                    RcDetailVo priceRcDetailVo = new RcDetailVo();
                    priceRcDetailVo.setTitle("可订价格");
                    String content2;
                    if (mbTravelstandHotelPriceVo.getPriceUpperLimit() != null) {
                        content2 = mbTravelstandCurrencyExchangeService.showContext(mbTravelstandHotelPriceVo.getCurrencyCode(),mbTravelstandHotelPriceVo.getPriceUpperLimit());
                    } else {
                        content2 = "不限";
                    }
                    priceRcDetailVo.setContent(content2);
                    //设置星级信息
                    RcDetailVo starRcDetailVo = new RcDetailVo();
                    starRcDetailVo.setTitle("可订星级");
                    if (mbTravelstandHotelPriceVo.getStar() == null || mbTravelstandHotelPriceVo.getStar() == 0) {
                        starRcDetailVo.setContent(STAR_NAMES[0]);
                    } else {
                        starRcDetailVo.setContent(STAR_NAMES[mbTravelstandHotelPriceVo.getStar()] + "及以下");
                    }
                    areaPriceHotelForAppVoRcDetailVos.add(areaRcDetailVo);
                    areaPriceHotelForAppVoRcDetailVos.add(priceRcDetailVo);
                    areaPriceHotelForAppVoRcDetailVos.add(starRcDetailVo);
                    areaPriceHotelForAppVo.setRcDetail(areaPriceHotelForAppVoRcDetailVos);
                    areaPriceHotelForAppVo.setTitle(null);
                    hotelForAppVos.add(areaPriceHotelForAppVo);
                    //淡旺季
                    if (HotelSwitchEnum.QuarterSwitch.E.getCode().equals(mbTravelstandHotelVo.getQuarterSwitch())) {
                        HotelForAppVo quarterHotelForAppVo = new HotelForAppVo();
                        quarterHotelForAppVo.setTitle("淡旺季");
                        List<RcDetailVo> quarterHotelForAppVoRcDetailVos = new ArrayList<>();
                        List<MbTravelstandHotelQuarterVo> mbTravelstandHotelQuarterVoList = travelstandHotelQuarterService.list(new MbTravelstandHotelQuarterVo().setTsHotelId(mbTravelstandHotelVo.getId()).setTsHotelAreaId(areaConfigVo.getId()));
                        for (MbTravelstandHotelQuarterVo mbTravelstandHotelQuarterVo : mbTravelstandHotelQuarterVoList) {
                            //如果未设置淡旺季 开始结束时间则   默认不走淡旺季配置
                            if (Objects.isNull(mbTravelstandHotelQuarterVo.getBeginDate())
                                    || Objects.isNull(mbTravelstandHotelQuarterVo.getEndDate())) {
                                continue;
                            }
                            if (compareDate(eDate, mbTravelstandHotelQuarterVo.getBeginDate())<0
                                    || compareDate(sDate, mbTravelstandHotelQuarterVo.getEndDate())>0) {
                                continue;
                            }
                            RcDetailVo quarterPriceRcDetailVo = new RcDetailVo();
                            if (mbTravelstandHotelQuarterVo.getPriceUpperLimit() != null) {
                                quarterPriceRcDetailVo.setTitle("可订价格");
                                quarterPriceRcDetailVo.setContent(
                                        "CNY" + mbTravelstandHotelQuarterVo.getPriceUpperLimit().setScale(0, RoundingMode.HALF_UP) +
                                                "/间夜");
                            } else {
                                quarterPriceRcDetailVo.setTitle("可订价格");
                                quarterPriceRcDetailVo.setContent("不限");
                            }
                            quarterHotelForAppVoRcDetailVos.add(quarterPriceRcDetailVo);
                            RcDetailVo rcDetailVoQuarterTime = new RcDetailVo();
                            if (mbTravelstandHotelQuarterVo.getBeginDate() != null && mbTravelstandHotelQuarterVo.getEndDate() != null) {
                                rcDetailVoQuarterTime.setTitle("起止时间");
                                if(!DateUtil.dateToString(mbTravelstandHotelQuarterVo.getBeginDate(), DateUtil.DF_Y).equals(DateUtil.dateToString(mbTravelstandHotelQuarterVo.getEndDate(), DateUtil.DF_Y))){
                                    rcDetailVoQuarterTime.setContent(DateUtil.dateToString(mbTravelstandHotelQuarterVo.getBeginDate(), DateUtil.DF_MD) + "~次年" + DateUtil.dateToString(mbTravelstandHotelQuarterVo.getEndDate(), DateUtil.DF_MD));
                                }else {
                                    rcDetailVoQuarterTime.setContent(DateUtil.dateToString(mbTravelstandHotelQuarterVo.getBeginDate(), DateUtil.DF_MD) + "~" + DateUtil.dateToString(mbTravelstandHotelQuarterVo.getEndDate(), DateUtil.DF_MD));
                                }
                            } else {
                                rcDetailVoQuarterTime.setTitle("起止时间");
                                rcDetailVoQuarterTime.setContent("不限");
                            }
                            quarterHotelForAppVoRcDetailVos.add(rcDetailVoQuarterTime);
                        }
                        quarterHotelForAppVo.setRcDetail(quarterHotelForAppVoRcDetailVos);
                        hotelForAppVos.add(quarterHotelForAppVo);
                    }
                    //管控方式
                    HotelForAppVo controlHotelForAppVo = new HotelForAppVo();
                    List<RcDetailVo> controlHotelForAppVoRcDetailVos = new ArrayList<>();
                    log.info("管控方式"+ mbTravelstandHotelVo.getControlType());

                    String[] controlTypeArr = mbTravelstandHotelVo.getControlType().split(",");
                    Arrays.stream(controlTypeArr).forEach(item ->{
                        RcDetailVo controlRcDetailVo = new RcDetailVo();
                        controlRcDetailVo.setTitle("超标管控方式");
                        ControlTypeEnum controlTypeEnum = ControlTypeEnum.getEnumByCode(item);
                        controlRcDetailVo.setContent(controlTypeEnum == null ? null : controlTypeEnum.getName());
                        controlHotelForAppVoRcDetailVos.add(controlRcDetailVo);
                    });
                    controlHotelForAppVo.setRcDetail(controlHotelForAppVoRcDetailVos);
                    hotelForAppVos.add(controlHotelForAppVo);
                }
            }
        } else {
            //地区限价信息vo
            HotelForAppVo areaPriceHotelForAppVo = new HotelForAppVo();
            List<RcDetailVo> areaPriceHotelForAppVoRcDetailVos = new ArrayList<>();
            //设置地区名称
            RcDetailVo areaRcDetailVo = new RcDetailVo();
            areaRcDetailVo.setTitle("适用城市");
            areaRcDetailVo.setContent(hotelCityBo.getCityName());
            areaPriceHotelForAppVoRcDetailVos.add(areaRcDetailVo);
            //设置价格信息
            RcDetailVo priceRcDetailVo = new RcDetailVo();
            priceRcDetailVo.setTitle("可订价格");
            priceRcDetailVo.setContent("不限");
            areaPriceHotelForAppVoRcDetailVos.add(priceRcDetailVo);
            //设置星级信息
            RcDetailVo starRcDetailVo = new RcDetailVo();
            starRcDetailVo.setTitle("可订星级");
            starRcDetailVo.setContent("不限");
            areaPriceHotelForAppVoRcDetailVos.add(starRcDetailVo);
            areaPriceHotelForAppVo.setRcDetail(areaPriceHotelForAppVoRcDetailVos);
            hotelForAppVos.add(areaPriceHotelForAppVo);
            //管控方式vo
            HotelForAppVo controlHotelForAppVo = new HotelForAppVo();
            List<RcDetailVo> controlHotelForAppVoRcDetailVos = new ArrayList<>();
            //设置管控方式
            RcDetailVo controlRcDetailVo = new RcDetailVo();
            controlRcDetailVo.setTitle("超标管控方式");
            controlRcDetailVo.setContent("不限");
            controlHotelForAppVoRcDetailVos.add(controlRcDetailVo);
            controlHotelForAppVo.setRcDetail(controlHotelForAppVoRcDetailVos);
            hotelForAppVos.add(controlHotelForAppVo);
        }
        return hotelForAppVos;
    }



    public JSONResult downloadAreaConfTemplate(String orgId, HttpServletResponse response) {
        try {
            String fileName = FileTemplateEnum.SyncHotelAreaConfTemplate.getDealMsg();
            InputStream inputStream = ExcelUtils.class.getClassLoader().getResourceAsStream(String.format("syncorgexceltemplate/%s", fileName));
            XSSFWorkbook workBook = new XSSFWorkbook(inputStream);
            //浏览器下载
            response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE);
            response.setHeader("Content-Disposition", "attachment;filename=" + fileName);
            response.flushBuffer();
            workBook.write(response.getOutputStream());
            inputStream.close();
        } catch (IOException e) {
            log.error("下载模板异常", e);
            return JSONResult.errorMsg("下载模板异常");
        }
        return JSONResult.success(null);
    }

    public JSONResult downloadHotelAreaConfExcel(Long uploadId,String fileName, HttpServletResponse response) {
        URL urlfile = null;
        HttpURLConnection httpUrl = null;
        try {
            if (uploadId == null) {
                throw new CorpBusinessException(OrganizationResponseCodeEnum.PARAMS_ERROR);
            }
            HotelAreaConfUpload hotelAreaConfUpload = new HotelAreaConfUpload();
            hotelAreaConfUpload.setId(uploadId);
            HotelAreaConfUpload dbHotelAreaConfUpload = mbHotelAreaConfUploadMapper.selectByPrimaryKey(hotelAreaConfUpload);

            if(dbHotelAreaConfUpload == null || dbHotelAreaConfUpload.getFileUrl() == null){
                throw new CorpBusinessException(OrganizationResponseCodeEnum.BODY_NULL);
            }
            String url = dbHotelAreaConfUpload.getFileUrl();
            List<String> domains = commonApollo.getDomainWhiteList();
            if(CollectionUtils.isNotEmpty(domains)){
                throw new CorpBusinessException(ExceptionCodeEnum.Alert,"domain whiteList can not empty");
            }
            Boolean valid = false;
            for (int i = 0; i < domains.size(); i++) {
                valid =  VulDef.SecuritySSRF(url,domains.get(i));
                if(BooleanUtil.isTrue(valid)){
                    break;
                }
            }
            if(BooleanUtil.isFalse(valid)){
                throw new CorpBusinessException(ExceptionCodeEnum.Alert,"request url is not valid");
            }

            urlfile = new URL(url);
            if (!StringUtils.isBlank(commonApollo.getProxyUrl()) && commonApollo.getProxyPort() != null){
                Proxy proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress(commonApollo.getProxyUrl(), commonApollo.getProxyPort()));
                httpUrl = (HttpURLConnection) urlfile.openConnection(proxy);
            }else {
                httpUrl = (HttpURLConnection) urlfile.openConnection();
            }
            httpUrl.connect();
            XSSFWorkbook workBook = new XSSFWorkbook(httpUrl.getInputStream());
            //浏览器下载
            response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE);
            response.setHeader("Content-Disposition", "attachment;filename=" + fileName);
            response.flushBuffer();
            workBook.write(response.getOutputStream());
            httpUrl.disconnect();
        } catch (IOException e) {
            log.error("下载模板异常", e);
            return JSONResult.errorMsg("下载模板异常");
        } finally {
            httpUrl.disconnect();
        }
        return JSONResult.success(null);
    }

    public <T> void syncHotelAreaConfExcelV1(MultipartFile file,String orgId) {

        // 同步上传oss
        String fileUrl = basicOssClientLoader.uploadFile(file);

        HotelAreaConfUpload hotelAreaConfUpload = saveHotelAreaConfUploadRecord(orgId, file, 0, fileUrl);


        BizImportTaskImpl<HotelAreaConfUpload,String> task = new BizImportTaskImpl<>();
        task.setBasic(hotelAreaConfUpload);
        task.setExt(orgId);

        ExcelImportProcessor processor = factory.getMessageHandler("hotel_area_v1");
        if (processor != null) {

            BizImportResult<UploadErrorLog,HotelAreaConfColumnVo> excelDataRes = processor.assembleListFromExcel(task,file);

            List<HotelAreaConfColumnVo> dataList = excelDataRes.getData();

            int allNum = dataList.stream().collect(Collectors.groupingBy(HotelAreaConfColumnVo::getLineNo)).size();
            hotelAreaConfUpload.setUploadNumber(allNum);

            mbHotelAreaConfUploadMapper.updateByPrimaryKeySelective(hotelAreaConfUpload);

            BizImportResult<UploadErrorLog,HotelAreaConfColumnVo> checkExcelDataRes =  processor.checkExcelData(dataList);

            BizImportPreInsertResult<UploadErrorLog,HotelAreaConfColumnVo, T> checkDbDataRes =  processor.checkDbDataWithPreInsert(dataList,task);

            List<UploadErrorLog> errorList = new ArrayList<>();


            if(excelDataRes != null) {
                errorList.addAll(excelDataRes.getError());
            }
            if(checkExcelDataRes != null) {
                errorList.addAll(checkExcelDataRes.getError());
            }
            if(checkDbDataRes != null) {
                errorList.addAll(checkDbDataRes.getError());
            }

            if(CollectionUtil.isNotEmpty(errorList)){
                // 有报错且全量回滚
                // 记录错误日志 并更新记录状态
                processor.writeErrorLog(errorList,task);

                return;
            }


            // 最后开启整体事务插入，防止脏数据写入后未删除
            transactionUtils.runInTransaction(() -> {
                // 更新db 并更新记录状态
                processor.writeIfVerifyPassed(dataList,task);

            });

        }
    }

    public JSONResult  syncHotelAreaConfExcel(HttpServletRequest request, String orgId) {

        MultipartHttpServletRequest multipartHttpServletRequest = (MultipartHttpServletRequest) request;
        List<MultipartFile> files = multipartHttpServletRequest.getFiles("file");
        MultipartFile file = files.get(0);
        if (file == null) {
            throw new CorpBusinessException(OrganizationResponseCodeEnum.PARAMS_ERROR);
        }
        if (!file.getOriginalFilename().endsWith(".xls") && !file.getOriginalFilename().endsWith(".xlsx")) {
            throw new CorpBusinessException(OrganizationResponseCodeEnum.PARAMS_ERROR);
        }
        if(Objects.isNull(orgId)) {
            throw new CorpBusinessException(OrganizationResponseCodeEnum.ORG_ID_NULL);
        }

        this.syncHotelAreaConfExcelV1(file,orgId);
        /*
          Workbook workbook = null;

        try {
            if (file.getOriginalFilename().endsWith(".xls")) {
                workbook = new HSSFWorkbook(file.getInputStream());
            } else if (file.getOriginalFilename().endsWith(".xlsx")) {
                workbook = new XSSFWorkbook(file.getInputStream());
            }
        } catch (IOException e) {
            log.error("上传差标酒店地区异常", e);
            return JSONResult.errorMsg("电子表格格式错误，请重新导入！");
        }
        // 取出第一页
        Sheet sheet = workbook.getSheetAt(0);
        //校验模板
        checkAreaConfTemplate(sheet);
        // Excel内容
        List<HotelAreaConfColumnVo> beanListFromExcel =
                excelUtils.getBeanListFromExcelTwo(sheet, HotelAreaConfColumnVo.class);

        if (CollectionUtils.isEmpty(beanListFromExcel)) {
            throw new CorpBusinessException(OrganizationResponseCodeEnum.HOTEL_TRAVEL_QUARTER_EMPTY);
        }

        // 同步上传oss
        String fileUrl = basicOssClientLoader.uploadFile(file);

        HotelAreaConfUpload hotelAreaConfUpload = saveHotelAreaConfUploadRecord(orgId, file, beanListFromExcel.size(), fileUrl);

        CityInfoQuickDisplayRequest requestInSea = new CityInfoQuickDisplayRequest();
        requestInSea.setForeignCity(false);
        requestInSea.setDisplayType(Arrays.asList(CAPITAL_CITY,MUNICIPALITY_CITY,SPECIFICALLY_CITY));
        CityInfoQuickDisplayResponse cityInfoInSeaDto = basicDataClientLoader.queryChineseCity(requestInSea);

        CityInfoQuickDisplayRequest requestOutSea = new CityInfoQuickDisplayRequest();
        requestOutSea.setForeignCity(true);
        requestOutSea.setDisplayType(Arrays.asList(COMMON_COUNTRY));
        CityInfoQuickDisplayResponse cityInfoOutSeaDto = basicDataClientLoader.queryChineseCity(requestOutSea);

        defaultThreadPoolExecutor.execute(() -> {
            try {
                doHandleHotelAreaConfExcel(orgId, beanListFromExcel, hotelAreaConfUpload,cityInfoInSeaDto,cityInfoOutSeaDto);
            } catch (Exception e) {
                e.printStackTrace();
            }
        });
*/

        return JSONResult.ok();
    }

    public HotelAreaConfUploadPageResponseVo  selectAreaConfUploadPage(HotelAreaConfPageRequestVo requestVo) {
        PageHelper.startPage(requestVo.getPageNum(), requestVo.getPageSize());
        Example uploadDetailExample = new Example(HotelAreaConfUpload.class);
        Example.Criteria criteria = uploadDetailExample.createCriteria().andEqualTo("orgId", requestVo.getOrgId());
        if (requestVo.getBeginDate() != null) {
            criteria.andGreaterThanOrEqualTo("createTime", requestVo.getBeginDate());
        }
        if (requestVo.getEndDate() != null) {
            criteria.andLessThanOrEqualTo("createTime", requestVo.getEndDate());
        }
        if (StringUtils.isNotBlank(requestVo.getOperatorName())) {
            criteria.andLike("operatorName", "%" + requestVo.getOperatorName() + "%");
        }
        uploadDetailExample.setOrderByClause("create_time DESC");
        List<HotelAreaConfUpload> hotelQuarterUploads = mbHotelAreaConfUploadMapper.selectByExample(uploadDetailExample);
        HotelAreaConfUploadPageResponseVo pageResponseVo = new HotelAreaConfUploadPageResponseVo();
        PageInfo pageInfo = new PageInfo<>(hotelQuarterUploads);
        Page<HotelAreaConfUpload> page = new Page(pageInfo.getPageNum(), pageInfo.getPageSize(), pageInfo.getPages(),
                pageInfo.getTotal(), hotelQuarterUploads);
        List<HotelAreaConfUploadInfoResponseVo> responseVos = new ArrayList<>();
        page.getList().stream().filter(Objects::nonNull).forEach(item -> {

            Example uploadError = new Example(UploadErrorLog.class);
            uploadError.createCriteria().andEqualTo("bizId", item.getId())
                    .andEqualTo("type", UploadTypeStatusEnum.AREA_CONF.getCode());
            List<UploadErrorLog> uploadErrorList =
                    mbUploadErrorLogMapper.selectByExample(uploadError);

            HotelAreaConfUploadInfoResponseVo responseVo = new HotelAreaConfUploadInfoResponseVo();
            responseVo.setCreateTime(DateUtil.dateToString(item.getCreateTime(), DateUtil.DF_YMD_HMS));
            responseVo.setFailNumber(uploadErrorList.size());
            responseVo.setFileName(item.getFileName());
            responseVo.setUploadNumber(item.getUploadNumber());
            responseVo.setOperatorName(item.getOperatorName());
            responseVo.setSuccessNumber(item.getUploadNumber()-item.getFailNumber());
            responseVo.setStatus(item.getStatus());
            responseVo.setUploadId(item.getId());
            responseVo.setFileUrl(item.getFileUrl());
            responseVos.add(responseVo);
        });
        pageResponseVo.setUploadDetailResponseVos(responseVos);//返回前端结果
        pageResponseVo.setCurrentPage(requestVo.getPageNum());
        pageResponseVo.setPageSize(requestVo.getPageSize());
        pageResponseVo.setTotalCount(Integer.parseInt(pageInfo.getTotal() + ""));
        pageResponseVo.setTotalPage(page.getTotalPage());
        return pageResponseVo;
    }

    public HotelAreaConfUploadErrorLogPageResponseVo  selectAreaConfUploadDetailPage(HotelAreaConfDetailPageRequestVo requestVo) {
        PageHelper.startPage(requestVo.getPageNum(), requestVo.getPageSize());
        Example uploadDetailExample = new Example(UploadErrorLog.class);
        uploadDetailExample.createCriteria().andEqualTo("bizId", requestVo.getBizId())
                .andEqualTo("type", UploadTypeStatusEnum.AREA_CONF.getCode());
        List<UploadErrorLog> hotelQuarterUploadDetails =
                mbUploadErrorLogMapper.selectByExample(uploadDetailExample);
        HotelAreaConfUploadErrorLogPageResponseVo pageResponseVo = new HotelAreaConfUploadErrorLogPageResponseVo();
        PageInfo pageInfo = new PageInfo<>(hotelQuarterUploadDetails);
        Page<UploadErrorLog> page = new Page(pageInfo.getPageNum(), pageInfo.getPageSize(),
                pageInfo.getPages(), pageInfo.getTotal(), hotelQuarterUploadDetails);
        List<UploadErrorLogResponseVo> responseVos = new ArrayList<>();
        page.getList().stream().filter(Objects::nonNull).forEach(item -> {
            UploadErrorLogResponseVo responseVo = new UploadErrorLogResponseVo();
            responseVo.setLine(item.getLine());
            responseVo.setFiledReason(item.getFailedReason());
            responseVo.setStatus(UploadErrorCodeEnum.AREA_CONF.getDesc());
            responseVos.add(responseVo);
        });
        pageResponseVo.setUploadErrorLogVos(responseVos);//返回前端结果
        pageResponseVo.setCurrentPage(requestVo.getPageNum());
        pageResponseVo.setPageSize(requestVo.getPageSize());
        pageResponseVo.setTotalCount(Integer.parseInt(pageInfo.getTotal() + ""));
        pageResponseVo.setTotalPage(page.getTotalPage());
        return pageResponseVo;
    }

    public void downloadHotelAreaConf(HotelCityDownLoadRequestVo quarterVo, HttpServletResponse response) {
        if (quarterVo.getOrgId() == null) {
            throw new CorpBusinessException(OrganizationResponseCodeEnum.ORG_ID_NULL);
        }
        if (CollectionUtils.isEmpty(quarterVo.getIds())) {
            throw new CorpBusinessException(OrganizationResponseCodeEnum.PARAMS_ERROR);
        }
        List<HotelAreaConfColumnVo> responseVos = new ArrayList<>();
        for (int j = 0; j < quarterVo.getIds().size(); j++) {
            Long areaId = quarterVo.getIds().get(j);
            AreaConfigVo areaConfigVo = new AreaConfigVo(){{
                setOrgId(quarterVo.getOrgId());
                setId(areaId);
            }};
            List<TravelStandardCityConfig> cityConfigVoList = cityConfigMapper.listByOrgIdAreaId(areaConfigVo.getId(), areaConfigVo.getOrgId());
            if (CollectionUtils.isEmpty(cityConfigVoList)) {
                continue;
            }
            List<HotelCityBo> cityBoList = basicDataClientLoader.searchByCityIds(cityConfigVoList.stream()
                    .map(TravelStandardCityConfig::getCityCode).collect(Collectors.toList()));
            if(CollectionUtils.isNotEmpty(cityBoList)) {
                Map<String, HotelCityBo>  cityMap = cityBoList.stream().collect(Collectors.toMap(
                        HotelCityBo::getCityId, hotelCityBo -> hotelCityBo));
                for (TravelStandardCityConfig travel : cityConfigVoList) {
                    if(CollectionUtils.isNotEmpty(cityMap) && travel.getCityCode() != null
                            && !Objects.isNull(cityMap.get(travel.getCityCode()))) {
                        // 城市名称
                        travel.setCityName(cityMap.get(travel.getCityCode()).getCityName());
                    }
                }
            }

            //查找该组织下的所有地区id
            TravelStandardAreaConfig areaConfig = areaConfigMapper.selectByPrimaryKey(areaConfigVo.getId());
            String isOverSea = "";

            Map<String,ProvinceInfoVO> cityMappingProvince = new HashMap<>();

            if(AreaTypeEnum.HOTEL_TYPE_0.getCode().equals(areaConfig.getHotelType())){
                isOverSea = "否";
                List<String> cityNames = cityConfigVoList.stream().map(TravelStandardCityConfig::getCityName).collect(Collectors.toList());
                cityMappingProvince = basicDataClientLoader.batchQueryChinaCityMappingByName(cityNames);
            }else {
                isOverSea = "是";
                List<String> cityNames = cityConfigVoList.stream().map(TravelStandardCityConfig::getCountryName).collect(Collectors.toList());
                cityMappingProvince = basicDataClientLoader.batchQueryNotChinaCityMappingByName(cityNames);
            }


            for (int i = 0; i < cityConfigVoList.size(); i++) {
                HotelAreaConfColumnVo hotelAreaConfColumnVo = new HotelAreaConfColumnVo();
                TravelStandardCityConfig item = cityConfigVoList.get(i);
                hotelAreaConfColumnVo.setAreaName(areaConfig.getAreaName());
                if(ObjectUtil.isNull(item.getCityName())){
                    item.setCityName(item.getCountryName());
                }
                if(ObjectUtil.isNotNull(cityMappingProvince.get(item.getCityName()))){
                    hotelAreaConfColumnVo.setProvinceName(cityMappingProvince.get(item.getCityName()).getProvinceName());
                }
                hotelAreaConfColumnVo.setCityName(item.getCityName());
                hotelAreaConfColumnVo.setIsOversea(isOverSea);
                responseVos.add(hotelAreaConfColumnVo);
            }
        }



        SecureRandom random = new SecureRandom();
        StringBuilder fileName = new StringBuilder("地区城市批量导出数据").append(DateUtil.dateToString(new Date(),
                DateUtil.DFYMD)).append(random.nextInt(900000) + 100000);
        ExcelPostEnum excelPostEnum = ExcelPostEnum.xlsx;
        ExcelCreateVO<HotelAreaConfColumnVo> vo = ExcelCreateVO.<HotelAreaConfColumnVo>builder()
                .fileName(fileName.toString())
                .dataList(responseVos)
                .postfix(excelPostEnum)
                .cls(HotelAreaConfColumnVo.class)
                .sheetName("地区城市数据")
                .build();
        excelUtils.downloadExcelDocument(response, vo);
    }

    private HotelAreaConfUpload saveHotelAreaConfUploadRecord(String orgId, MultipartFile file,Integer size, String fileUrl) {
        // 上传记录表更新
        HotelAreaConfUpload hotelAreaConfUpload = new HotelAreaConfUpload();
        hotelAreaConfUpload.setFileName(file.getOriginalFilename());
        hotelAreaConfUpload.setFileUrl(fileUrl);
        hotelAreaConfUpload.setFailNumber(0);
        hotelAreaConfUpload.setSuccessNumber(0);
        hotelAreaConfUpload.setUploadNumber(size);
        hotelAreaConfUpload.setOrgId(orgId);
        hotelAreaConfUpload.setStatus(QuarterImportExcelRecordStatusEnum.U.getDealCode());
        hotelAreaConfUpload.setOperatorName(UserInfoContext.getContextParams(BaseUserInfo.class).getUserName());

        mbHotelAreaConfUploadMapper.insertSelective(hotelAreaConfUpload);
        return hotelAreaConfUpload;
    }

    private void doHandleHotelAreaConfExcel(String orgId, List<HotelAreaConfColumnVo> beanListFromExcel, HotelAreaConfUpload hotelAreaConfUpload,
                                            CityInfoQuickDisplayResponse cityInfoInSeaDto,CityInfoQuickDisplayResponse cityInfoOutSeaDto) {




        List<HotelAreaConfColumnVo> listError =  new ArrayList<>();
        // 需要新增的地区
        List<HotelAreaConfColumnVo> needAddOutSeaCityList  = new ArrayList<>();
        // 需要新增的城市
        List<HotelAreaConfColumnVo> needAddInSeaCityList = new ArrayList<>();
        // 剔除空格或者空行
        beanListFromExcel.forEach(StrUtils::fieldRemoveWarp);
        // 检验数据并输出数组
        checkExcelFromDb(orgId, beanListFromExcel, cityInfoInSeaDto, cityInfoOutSeaDto, listError, needAddOutSeaCityList, needAddInSeaCityList);

        // 需要新增的地区--db
        List<HotelAreaConfColumnVo> finalNeedAddOutSeaCityList  = new ArrayList<>();
        // 需要新增的城市--db
        List<HotelAreaConfColumnVo> finalNeedAddInSeaCityList = new ArrayList<>();
        // 过滤一下需要上传的数据和存在错误的数据，效果，同一行有错误的数据，这一行不上传，记录为失败记录
        buildFinalDbExcel(listError, needAddOutSeaCityList, needAddInSeaCityList, finalNeedAddOutSeaCityList, finalNeedAddInSeaCityList);
        // 更新db
        saveHotelAreaConf(orgId, finalNeedAddOutSeaCityList, finalNeedAddInSeaCityList);
        // 更新日志
        int errorNum = listError.stream().collect(Collectors.groupingBy(HotelAreaConfColumnVo::getLineNo)).size();
        hotelAreaConfUpload.setSuccessNumber(beanListFromExcel.size() - errorNum);
        hotelAreaConfUpload.setFailNumber(errorNum);
        if (Objects.nonNull(hotelAreaConfUpload.getFailNumber()) && hotelAreaConfUpload.getFailNumber() > 0) {
            hotelAreaConfUpload.setStatus(QuarterImportExcelRecordStatusEnum.F.getDealCode());
        }else {
            hotelAreaConfUpload.setStatus(QuarterImportExcelRecordStatusEnum.E.getDealCode());
        }
        mbHotelAreaConfUploadMapper.updateByPrimaryKeySelective(hotelAreaConfUpload);

        // 批量写入error日志
        saveAreaConfUploadErrorLog(hotelAreaConfUpload, listError);
    }

    private void buildFinalDbExcel(List<HotelAreaConfColumnVo> listError, List<HotelAreaConfColumnVo> needAddOutSeaCityList, List<HotelAreaConfColumnVo> needAddInSeaCityList, List<HotelAreaConfColumnVo> finalNeedAddOutSeaCityList, List<HotelAreaConfColumnVo> finalNeedAddInSeaCityList) {
        List<String> lineErrorList = listError.stream().map(o -> o.getLineNo()).distinct().collect(Collectors.toList());
        for (int i = 0; i < needAddOutSeaCityList.size(); i++) {
            if(lineErrorList.contains(needAddOutSeaCityList.get(i).getLineNo())){
                continue;
            }
            finalNeedAddOutSeaCityList.add(needAddOutSeaCityList.get(i));
        }
        for (int i = 0; i < needAddInSeaCityList.size(); i++) {
            if(lineErrorList.contains(needAddInSeaCityList.get(i).getLineNo())){
                continue;
            }
            finalNeedAddInSeaCityList.add(needAddInSeaCityList.get(i));
        }
    }


    private void checkExcelFromDb(String orgId, List<HotelAreaConfColumnVo> beanListFromExcel, CityInfoQuickDisplayResponse cityInfoInSeaDto, CityInfoQuickDisplayResponse cityInfoOutSeaDto, List<HotelAreaConfColumnVo> listError, List<HotelAreaConfColumnVo> needAddOutSeaCityList, List<HotelAreaConfColumnVo> needAddInSeaCityList) {
        // 获取当前db存在的数据，用于excel校验
        List<TravelStandardCityConfig> cityInfoList = cityConfigMapper.listByOrgId(orgId, null);

        List<TravelStandardCityConfig> confCityInfoList = new ArrayList<>();
        for (int i = 0; i < cityInfoList.size(); i++) {
            TravelStandardCityConfig item = cityInfoList.get(i);
            if(ObjectUtil.isNull(item.getCityName())){
                item.setCityCode(item.getCountryCode());
                item.setCityName(item.getCountryName());
            }
            if( AreaTypeEnum.TYPE_0.getCode().equals(item.getAreaType())){
                confCityInfoList.add(item);
            }
        }

        Map<String,TravelStandardCityConfig> cityDataMap = confCityInfoList.stream().collect(Collectors.toMap(TravelStandardCityConfig::getCityName, p -> p, (k, v) -> k));

        //查找该组织下的所有地区id
        List<AreaVo> areaConfigList = areaConfigService.getAreaConfigList(new AreaConfigVo(){{
            setOrgId(orgId);
            setStatus(NumberUtils.INTEGER_ZERO);
            setAreaType(AreaTypeEnum.TYPE_0.getCode());
        }});

        Map<Long,AreaVo> areaDataMap = areaConfigList.stream().collect(Collectors.toMap(data -> data.getId(), data -> data));
        Map<String,AreaVo> areaNameDataMap = areaConfigList.stream().collect(Collectors.toMap(data -> data.getName(), data -> data));


        // 国内省份匹配 上海--2 北京--1
        Map<String,String> provinceInSeaNameToId = cityInfoInSeaDto.getProvinceInfoVO().stream().collect(Collectors.toMap(data -> data.getProvinceName(), data -> data.getProvinceId(), (k, v) -> k));


        // 国外省份匹配
        Map<String, ProvinceInfoVO> provinceOutSeaNameToId = cityInfoOutSeaDto.getProvinceInfoVO().stream().collect(Collectors.toMap(data -> data.getProvinceName(), data -> data, (k, v) -> k));


        Map<String,String> cityMapAreaHistory = new HashMap<>();


        Map<String,String> areaExcelHistory = new HashMap<>();



        List<HotelAreaConfColumnVo> multiBeanList = new ArrayList<>();
        // 平铺excel，一行多分号分割的地级市平铺为多列
        for (int i = 0; i < beanListFromExcel.size(); i++) {
            HotelAreaConfColumnVo column = beanListFromExcel.get(i);
           if(ObjectUtil.isNull(column.getCityName())){
               multiBeanList.add(column);
           }else {
               String[] parts = column.getCityName().split("；");
               for (String part : parts) {
                   HotelAreaConfColumnVo item = new HotelAreaConfColumnVo();
                   BeanUtils.copyProperties(column,item);
                   item.setCityName(part);
                   multiBeanList.add(item);
               }
           }
        }


        for (int i = 0; i < multiBeanList.size(); i++) {
            HotelAreaConfColumnVo column = multiBeanList.get(i);
            column.setHotelType(!"是".equals(column.getIsOversea())?AreaTypeEnum.HOTEL_TYPE_0.getCode():AreaTypeEnum.HOTEL_TYPE_1.getCode());
            StringBuffer errorLog = new StringBuffer();
            try {
                if (ObjectUtil.isNull(column.getAreaName())) {
                    errorLog.append("地区名称为空");
                    continue;
                }
                if(ObjectUtil.isNull(column.getProvinceName()) && ObjectUtil.isNull(column.getCityName())){
                    if(ObjectUtil.isNotNull(areaNameDataMap.get(column.getAreaName()))){
                        errorLog.append("地区名称【"+column.getAreaName()+"】已存在");
                    }
                    continue;
                }
                if(ObjectUtil.isNotNull(areaNameDataMap.get(column.getAreaName()))){
                    if(!areaNameDataMap.get(column.getAreaName()).getHotelType().equals(column.getHotelType())){
                        errorLog.append("该地区的是否海外配置错误");
                        continue;
                    }
                }

                if (AreaTypeEnum.HOTEL_TYPE_0.getCode().equals(column.getHotelType())){
                    // 国内逻辑校验
                    if(ObjectUtil.isNull(column.getProvinceName())){
                        errorLog.append("省/自治区/直辖市/州为空");
                        continue;
                    }
                    String provinceId = provinceInSeaNameToId.get(column.getProvinceName());
                    if(ObjectUtil.isNull(provinceId)){
                        errorLog.append("【"+column.getProvinceName()+"】不存在");
                        continue;
                    }
                    if(ObjectUtil.isNull(column.getCityName())){
                        errorLog.append("地级市/地区/自治州/盟/国家为空");
                        continue;
                    }
                    List<CityBasicInfoVO> cityInSeaList = cityInfoInSeaDto.getCityInfoVO().get(provinceId);
                    Optional<CityBasicInfoVO> cityBasicInfoVO = cityInSeaList.stream() .filter(a -> column.getCityName().equals(a.getCityName())) .findFirst();
                    if (!cityBasicInfoVO.isPresent()) {
                        errorLog.append("【"+column.getProvinceName()+"】下"+column.getCityName()+"不存在");
                        continue;
                    }else{
                        column.setCityCode(cityBasicInfoVO.get().getCityCode());
                    }
                }else{
                    // 国外数据校验
                    if(ObjectUtil.isNull(column.getProvinceName())){
                        errorLog.append("省/自治区/直辖市/州为空");
                        continue;
                    }
                    ProvinceInfoVO provinceInfoVO = provinceOutSeaNameToId.get(column.getProvinceName());
                    if(ObjectUtil.isNull(provinceInfoVO)){
                        errorLog.append("【"+column.getProvinceName()+"】不存在");
                        continue;
                    }
                    if(ObjectUtil.isNull(column.getCityName())){
                        errorLog.append("地级市/地区/自治州/盟/国家为空");
                        continue;
                    }
                    List<CityBasicInfoVO> cityOutSeaList = cityInfoOutSeaDto.getCityInfoVO().get(column.getProvinceName());
                    Optional<CityBasicInfoVO> cityBasicInfoVO = cityOutSeaList.stream() .filter(a -> column.getCityName().equals(a.getCityName())) .findFirst();
                    if (!cityBasicInfoVO.isPresent()) {
                        errorLog.append("【"+column.getProvinceName()+"】下"+column.getCityName()+"不存在");
                        continue;
                    }else{
                        column.setCityCode(cityBasicInfoVO.get().getCityCode());
                    }
                }


                TravelStandardCityConfig var1 = cityDataMap.get(column.getCityName());
                if(ObjectUtil.isNotNull(var1)){
                    AreaVo areaVo = areaDataMap.get(var1.getAreaId());
                    if(ObjectUtil.isNotNull(areaVo) && !column.getAreaName().equals(areaVo.getName())){
                        errorLog.append("【"+column.getCityName()+"】已在【"+areaVo.getName()+"】地区配置");
                        continue;
                    }else{
                        errorLog.append("【"+column.getCityName()+"】已配置");
                        continue;
                    }
                }

                if(cityMapAreaHistory.containsKey(column.getCityName())){
                    errorLog.append("【"+column.getCityName()+"】在多个地区配置内存在");
                    continue;
                }else {
                    cityMapAreaHistory.put(column.getCityName(), column.getAreaName());
                }

                if(areaExcelHistory.get(column.getAreaName())!=null && !column.getHotelType().equals(areaExcelHistory.get(column.getAreaName()))){
                    errorLog.append("【"+column.getCityName()+"】存在多个是否海外配置");
                    continue;
                }else {
                    areaExcelHistory.put(column.getAreaName(), column.getHotelType());
                }
            } catch (Exception e) {
                errorLog.append("未知异常"+e.getMessage());
            } finally {
                // no-error
                if(ObjectUtil.isEmpty(errorLog)){
                    if(AreaTypeEnum.HOTEL_TYPE_0.getCode().equals(column.getHotelType())){
                        needAddInSeaCityList.add(column);
                    }
                    if(AreaTypeEnum.HOTEL_TYPE_1.getCode().equals(column.getHotelType())){
                        needAddOutSeaCityList.add(column);
                    }
                }else{
                    column.setFailReason(errorLog.toString());
                    listError.add(column);
                }
            }
        }
    }

    public void saveHotelAreaConf(String orgId, List<HotelAreaConfColumnVo> needAddOutSeaCityList, List<HotelAreaConfColumnVo> needAddInSeaCityList) {
        Map<String, AreaVo> areaNameDataMap;
        // 海内地区新增
        mergeArea(orgId, needAddInSeaCityList.stream().collect(Collectors.toMap(data -> data.getAreaName(), p -> p, (k, v) -> k)));

        // 海外地区新增
        mergeArea(orgId, needAddOutSeaCityList.stream().collect(Collectors.toMap(data -> data.getAreaName(), data -> data, (k, v) -> k)));

        //重新查找该组织下的所有地区id
        List<AreaVo> newAreaConfigList = areaConfigService.getAreaConfigList(new AreaConfigVo(){{
            setOrgId(orgId);
            setStatus(NumberUtils.INTEGER_ZERO);
            setAreaType(AreaTypeEnum.TYPE_0.getCode());
        }});

        // 海外市区新增
        Map<String,List<HotelAreaConfColumnVo>> needAddOutSeaMap = needAddOutSeaCityList.stream().collect(Collectors.groupingBy(data -> data.getAreaName()));

        areaNameDataMap = newAreaConfigList.stream().collect(Collectors.toMap(data -> data.getName(), data -> data, (k, v) -> k));

        for (String key : needAddOutSeaMap.keySet()) {
            AddCityVo addCityVo = new AddCityVo();
            addCityVo.setAreaId(areaNameDataMap.get(key).getId());
            addCityVo.setOrgid(orgId);
            addCityVo.setHotelType(AreaTypeEnum.HOTEL_TYPE_1.getCode());
            List<CityNode> city = new ArrayList<>();
            for (int i = 0; i < needAddOutSeaMap.get(key).size(); i++) {
                HotelAreaConfColumnVo item = needAddOutSeaMap.get(key).get(i);
                CityNode cityNode =  new CityNode();
                cityNode.setCityCode(item.getCityCode());
                cityNode.setCityName(item.getCityName());
                city.add(cityNode);
            }
            addCityVo.setCity(city);
            if(CollectionUtil.isEmpty(city)){
                continue;
            }
            cityConfigService.addCountry(addCityVo);

        }

        // 海内市区新增
        Map<String,List<HotelAreaConfColumnVo>> needAddInSeaMap = needAddInSeaCityList.stream().collect(Collectors.groupingBy(data -> data.getAreaName()));

        for (String  key: needAddInSeaMap.keySet()) {
            AddCityVo addCityVo = new AddCityVo();
            addCityVo.setAreaId(areaNameDataMap.get(key).getId());
            addCityVo.setOrgid(orgId);
            addCityVo.setHotelType(AreaTypeEnum.HOTEL_TYPE_0.getCode());
            List<CityNode> city1 = new ArrayList<>();
            for (int i = 0; i < needAddInSeaMap.get(key).size(); i++) {
                HotelAreaConfColumnVo item = needAddInSeaMap.get(key).get(i);
                if(ObjectUtil.isNull(item.getCityCode())){
                    continue;
                }
                CityNode cityNode =  new CityNode();
                cityNode.setCityCode(item.getCityCode());
                cityNode.setCityName(item.getCityName());
                city1.add(cityNode);
            }
            addCityVo.setCity(city1);
            if(CollectionUtil.isEmpty(city1)){
                continue;
            }
            cityConfigService.addCity(addCityVo);

        }
    }

    private void saveAreaConfUploadErrorLog(HotelAreaConfUpload hotelAreaConfUpload, List<HotelAreaConfColumnVo> listError) {
        List<UploadErrorLog> errorLogList = new ArrayList<>();
        for (int i = 0; i < listError.size(); i++) {
            UploadErrorLog uploadErrorLog = new UploadErrorLog();
            uploadErrorLog.setBizId(hotelAreaConfUpload.getId());
            uploadErrorLog.setType(1);
            uploadErrorLog.setFailedReason(listError.get(i).getFailReason());
            uploadErrorLog.setLine(Integer.parseInt(listError.get(i).getLineNo()));
            errorLogList.add(uploadErrorLog);
        }
        if (CollectionUtils.isNotEmpty(errorLogList)) {
            mbUploadErrorLogMapper.insertList(errorLogList);
        }
    }

    private void mergeArea(String orgId, Map<String, HotelAreaConfColumnVo> map) {
        for (String key : map.keySet()) {
            TravelStandardAreaConfig config = new TravelStandardAreaConfig();
            config.setAreaName(key);
            config.setOrgId(orgId);
            int count = areaConfigMapper.existName(config);
            if (count == NumberUtils.INTEGER_ZERO) {
                //插入地区
                TravelStandardAreaConfig saveOrupdate = new TravelStandardAreaConfig();
                saveOrupdate.setOrgId(orgId);
                saveOrupdate.setAreaName(key);
                saveOrupdate.setAreaType(AreaTypeEnum.TYPE_0.getCode());
                saveOrupdate.setHotelType(map.get(key).getHotelType());
                areaConfigMapper.insertSelective(saveOrupdate);

                insertOperateLog(saveOrupdate);
                //将新的地区限价信息、淡旺季信息插入所有已存在的差标
                List<MbTravelstandHotelVo> mbTravelstandHotelVos = mbTravelstandHotelService.list(new MbTravelstandHotelVo() {{
                    setOrgId(orgId);
                }});
                for (MbTravelstandHotelVo mbTravelstandHotelVo : mbTravelstandHotelVos) {
                    //限价信息
                    MbTravelstandHotelPriceVo mbTravelstandHotelPriceVo = new MbTravelstandHotelPriceVo();
                    mbTravelstandHotelPriceVo.setTsHotelId(mbTravelstandHotelVo.getId());
                    mbTravelstandHotelPriceVo.setTsHotelAreaId(saveOrupdate.getId());
                    travelstandHotelPriceService.insert(mbTravelstandHotelPriceVo);
                    //淡旺季信息
                    MbTravelstandHotelQuarterVo mbTravelstandHotelQuarterVo = new MbTravelstandHotelQuarterVo();
                    mbTravelstandHotelQuarterVo.setTsHotelId(mbTravelstandHotelVo.getId());
                    mbTravelstandHotelQuarterVo.setTsHotelAreaId(saveOrupdate.getId());
                    travelstandHotelQuarterService.insert(mbTravelstandHotelQuarterVo);
                }
            }
        }
    }

    private void checkAreaConfTemplate(Sheet sheet) {
        List<String> headerList = Arrays.asList("*地区名称","省/自治区/直辖市/州（海外）","地级市/地区/自治州/盟/国家（海外）","是否海外，默认不填为否：国内（否：国内，是：国外）");
        for (int i = 0; i < headerList.size(); i++) {
            if (!sheet.getRow(1).getCell(i).getStringCellValue().equals(headerList.get(i))) {
                throw new CorpBusinessException(OrganizationResponseCodeEnum.HOTEL_TRAVEL_QUARTER_TEMPLATE_ERROR);
            }
        }
    }


    public List<HotelQuarterDownloadResponseVo> convertQuarterExcelVo(List<MbTravelstandHotelQuarterVo> list) {
        List<HotelQuarterDownloadResponseVo> responseVos = new ArrayList<>();
        if (CollectionUtils.isEmpty(list)) {
            return responseVos;
        }
        for (MbTravelstandHotelQuarterVo hotelQuarterVo : list) {
            HotelQuarterDownloadResponseVo hotelQuarterDownloadResponseVo = new HotelQuarterDownloadResponseVo();
            hotelQuarterDownloadResponseVo.setAreaName(hotelQuarterVo.getAreaName());
            hotelQuarterDownloadResponseVo.setBeginDate(hotelQuarterVo.getStartTime());
            hotelQuarterDownloadResponseVo.setEndDate((hotelQuarterVo.getEndTime()));
            if (hotelQuarterVo.getPriceUpperLimit() != null) {
                hotelQuarterDownloadResponseVo.setPriceUpperLimit(hotelQuarterVo.getPriceUpperLimit().stripTrailingZeros().toPlainString());
            }
            responseVos.add(hotelQuarterDownloadResponseVo);
        }
        return responseVos;
    }

    public static Boolean checkOnlyMMdd(String input) {

        Pattern pattern = Pattern.compile("\\d{2}-\\d{2}");
        Matcher matcher = pattern.matcher(input);

        Pattern pattern1 = Pattern.compile("(?<!\\d)\\d{4}-\\d{2}-\\d{2}(?!\\d)");
        Matcher matcher1 = pattern1.matcher(input);

        if (matcher.find() && !matcher1.find()) {
            return true;
        }

        return false;
    }

    private HotelQuarterUploadExcelInfo checkExcelInfo(List<HotelQuarterColumnVo> beanListFromExcel,
                                                       MbTravelstandHotel mbTravelstandHotel,
                                                       Map<String, Long> areaMap) {
        HotelQuarterUploadExcelInfo excelInfo = new HotelQuarterUploadExcelInfo();
        List<HotelQuarterUploadExcelInfo.HotelQuarterUploadDetailBo> uploadDetails = new ArrayList<>();
        List<HotelQuarterUploadExcelInfo.HotelQuarterUploadDetailBo> updateUploadDetails = new ArrayList<>();
        MbTravelstandHotelQuarterVo hotelQuarterVo = new MbTravelstandHotelQuarterVo();
        hotelQuarterVo.setTsHotelId(mbTravelstandHotel.getId());
        //表中的淡旺季List
        List<MbTravelstandHotelQuarterVo> dbQuarterList = travelstandHotelQuarterService.list(hotelQuarterVo);
        //现在界面输入的数据会存在只有开始时间和结束时间的情况
        dbQuarterList =
                dbQuarterList.stream().filter(r -> r.getStartTime() != null && r.getEndTime() != null).collect(Collectors.toList());
        String quarterSwitch = mbTravelstandHotel.getQuarterSwitch();
        for (HotelQuarterColumnVo quarterInfo : beanListFromExcel) {
            StringBuffer errorLog = new StringBuffer();
            HotelQuarterUploadExcelInfo.HotelQuarterUploadDetailBo uploadDetail =
                    new HotelQuarterUploadExcelInfo.HotelQuarterUploadDetailBo();
            Long areaId = null;
            if (StringUtils.isBlank(quarterInfo.getAreaName())) {
                errorLog.append("地区名称为空,");
            } else {
                areaId = areaMap.get(quarterInfo.getAreaName());
                if (areaId == null) {
                    errorLog.append("地区名称错误,");
                }
            }
            if(StringUtils.isNotBlank(quarterInfo.getBeginDate()) && !checkOnlyMMdd(quarterInfo.getBeginDate())){
                errorLog.append("淡旺季开始日期仅支持MM-dd格式,");
            }
            if(StringUtils.isNotBlank(quarterInfo.getEndDate()) && !checkOnlyMMdd(quarterInfo.getEndDate())){
                errorLog.append("淡旺季结束日期仅支持MM-dd格式,");
            }

            if (StringUtils.isBlank(quarterInfo.getBeginDate())) {
                errorLog.append("淡旺季开始日期为空,");
            }
            if (StringUtils.isBlank(quarterInfo.getEndDate())) {
                errorLog.append("淡旺季结束日期为空,");
            }
            uploadDetail.setStartTime(quarterInfo.getBeginDate());
            uploadDetail.setEndTime(quarterInfo.getEndDate());
            if(ObjectUtil.isNotNull(uploadDetail.getStartTime()) && ObjectUtil.isNotNull(uploadDetail.getEndTime())){
                Map<String, Date> res = HotelStandardConvert.getDateMap(uploadDetail.getStartTime(),uploadDetail.getEndTime());
                uploadDetail.setBeginDate(res.get("startDate"));
                uploadDetail.setEndDate(res.get("endDate"));
            }

            uploadDetail.setLine(Integer.valueOf(quarterInfo.getLineNo()));
            uploadDetail.setHotelAreaId(areaId);
            uploadDetail.setHotelAreaName(quarterInfo.getAreaName());
            if(!NumberUtils.isParsable(quarterInfo.getPriceUpperLimit()) && StringUtils.isNotBlank(quarterInfo.getPriceUpperLimit())){
                errorLog.append("淡旺季均价上限仅支持数字或者空,");
            }
            uploadDetail.setPriceUpperLimit(quarterInfo.getPriceUpperLimit());
            uploadDetail.setTsHotelId(mbTravelstandHotel.getId());
            uploadDetail.setFailedReason(errorLog.toString());
            uploadDetails.add(uploadDetail);
        }
        //基础数据都有（但未判断交叉淡旺季）的List
        List<HotelQuarterUploadExcelInfo.HotelQuarterUploadDetailBo> collect =
                uploadDetails.stream().filter(r -> StringUtils.isBlank(r.getFailedReason())).collect(Collectors.toList());
        for (HotelQuarterUploadExcelInfo.HotelQuarterUploadDetailBo hotelQuarterUploadDetailBo : collect) {
            for (HotelQuarterUploadExcelInfo.HotelQuarterUploadDetailBo hotelQuarterUploadDetail : collect) {
                if (Objects.equals(hotelQuarterUploadDetailBo.getHotelAreaId(),
                        hotelQuarterUploadDetail.getHotelAreaId()) && !hotelQuarterUploadDetail.getLine().equals(hotelQuarterUploadDetailBo.getLine())) {

                    DateRange range1 = new DateRange(makeDate( hotelQuarterUploadDetailBo.getStartTime()), makeDate(hotelQuarterUploadDetailBo.getEndTime()));
                    DateRange range2 = new DateRange(makeDate( hotelQuarterUploadDetail.getStartTime()), makeDate(hotelQuarterUploadDetail.getEndTime()));
                    // 判断是否交叉
                    if (hasOverlap(range1, range2)) {
                        if (hotelQuarterUploadDetailBo.getFailedReason() != null && !hotelQuarterUploadDetailBo.getFailedReason().contains("淡旺季时间段有交叉")) {
                            hotelQuarterUploadDetailBo.setFailedReason(hotelQuarterUploadDetailBo.getFailedReason() +
                                    "淡旺季时间段有交叉,");
                        }
                        if (hotelQuarterUploadDetail.getFailedReason() != null && !hotelQuarterUploadDetail.getFailedReason().contains("淡旺季时间段有交叉")) {
                            hotelQuarterUploadDetail.setFailedReason(hotelQuarterUploadDetail.getFailedReason() +
                                    "淡旺季时间段有交叉,");
                        }
                    }
                }
            }
            //停用时不用和库中数据比较，因为停用时导入会删掉历史数据
            if (HotelSwitchEnum.QuarterSwitch.E.getCode().equals(quarterSwitch)) {
                for (MbTravelstandHotelQuarterVo quarterVo : dbQuarterList) {
                    //开始时间和
                    if (Objects.equals(hotelQuarterUploadDetailBo.getHotelAreaId(),
                            quarterVo.getTsHotelAreaId())) {
                        // 与库中数据 区域id和开始结束时间一样的话，视为同一条记录
                        if (hotelQuarterUploadDetailBo.getStartTime().equals(quarterVo.getStartTime())
                                && hotelQuarterUploadDetailBo.getEndTime().equals(quarterVo.getEndTime()) ) {
                            hotelQuarterUploadDetailBo.setId(quarterVo.getId());
                            updateUploadDetails.add(hotelQuarterUploadDetailBo);

                        } else {
                            // 判断日期是否交叉替换为bit位来进行判断
                            DateRange range1 = new DateRange(makeDate( hotelQuarterUploadDetailBo.getStartTime()), makeDate(hotelQuarterUploadDetailBo.getEndTime()));
                            DateRange range2 = new DateRange(makeDate( quarterVo.getStartTime()), makeDate(quarterVo.getEndTime()));
                            if (hasOverlap(range1, range2)) {
                                if (hotelQuarterUploadDetailBo.getFailedReason() != null && !hotelQuarterUploadDetailBo.getFailedReason().contains("淡旺季时间段与历史数据有交叉")) {
                                    hotelQuarterUploadDetailBo.setFailedReason(hotelQuarterUploadDetailBo.getFailedReason() +
                                            "淡旺季时间段与历史数据有交叉,");
                                }
                            }
                        }

                    }
                }
            }

        }
        uploadDetails.forEach(r -> {
            String filedReason = r.getFailedReason();
            if (StringUtils.isNotBlank(filedReason)) {
                r.setFailedReason(filedReason.substring(0, filedReason.length() - 1));
            }
        });
        excelInfo.setAllDetailBos(uploadDetails);
        excelInfo.setUpdateDetailBos(updateUploadDetails);

        return excelInfo;
    }

    /**
     * 判断时间是否有交集
     *
     * @param startTime1
     * @param endTime1
     * @param startTime2
     * @param endTime2
     * @return
     */
    public static boolean checkTimeIntersection(Date startTime1, Date endTime1, Date startTime2, Date endTime2) {
        // 如果两个时间都一样的时候，默认为更新操作，不认为是时间冲突
        if(startTime1.getTime() == startTime2.getTime() && endTime1.getTime() == endTime2.getTime()){
            return false;
        }
        if ((startTime1.before(endTime2) || Objects.equals(startTime1.getTime(), endTime2.getTime())) && (endTime1.after(startTime2) || Objects.equals(endTime1.getTime(), startTime2.getTime()))) {
            return true;
        } else {
            return false;
        }
    }

    public void downloadHotelQuarterUploadInfo(Long uploadId, HttpServletResponse response) {
        HotelQuarterUpload quarterUpload = mbHotelQuarterUploadMapper.selectByPrimaryKey(uploadId);
        if (Objects.isNull(quarterUpload)) {
            throw new CorpBusinessException(OrganizationResponseCodeEnum.PLEASE_SELECT_CORRECT_UPLOAD_RECORD);
        }
        Example uploadDetailExample = new Example(HotelQuarterUploadDetail.class);
        uploadDetailExample.createCriteria().andEqualTo("uploadId", uploadId);
        List<HotelQuarterUploadDetail> hotelQuarterUploadDetails =
                mbHotelQuarterDetailUploadMapper.selectByExample(uploadDetailExample);
        List<HotelQuarterDownloadResponseVo> responseVos = new ArrayList<>();
        hotelQuarterUploadDetails.forEach(item -> {
            responseVos.add(new HotelQuarterDownloadResponseVo(item.getAreaName(), item.getPriceUpperLimit(),
                            item.getBeginDate(),
                    item.getEndDate()
            ));
        });
        String fileName;
        ExcelPostEnum excelPostEnum = ExcelPostEnum.xlsx;
        fileName = quarterUpload.getFileName().replace(".xlsx", "").replace(".xls", "");
        if (quarterUpload.getFileName().endsWith("xls")) {
            excelPostEnum = ExcelPostEnum.xls;
        }

        ExcelCreateVO<HotelQuarterDownloadResponseVo> vo = ExcelCreateVO.<HotelQuarterDownloadResponseVo>builder()
                .fileName(fileName)
                .dataList(responseVos)
                .postfix(excelPostEnum)
                .cls(HotelQuarterDownloadResponseVo.class)
                .build();
        excelUtils.downloadExcelDocument(response, vo);
    }

    public HotelQuarterUploadPageResponseVo selectQuarterUploadInfoPage(HotelQuarterUploadPageRequestVo requestVo) {
        PageHelper.startPage(requestVo.getPageNum(), requestVo.getPageSize());
        Example uploadDetailExample = new Example(HotelQuarterUpload.class);
        Example.Criteria criteria = uploadDetailExample.createCriteria().andEqualTo("orgId", requestVo.getOrgId());
        if (requestVo.getBeginDate() != null) {
            criteria.andGreaterThanOrEqualTo("createTime", requestVo.getBeginDate());
        }
        if (requestVo.getEndDate() != null) {
            criteria.andLessThanOrEqualTo("createTime", requestVo.getEndDate());
        }
        if (StringUtils.isNotBlank(requestVo.getTsHotelName())) {
            criteria.andLike("tsHotelName", "%" + requestVo.getTsHotelName() + "%");
        }
        if (StringUtils.isNotBlank(requestVo.getOperatorName())) {
            criteria.andLike("operatorName", "%" + requestVo.getOperatorName() + "%");
        }
        uploadDetailExample.setOrderByClause("create_time DESC");
        List<HotelQuarterUpload> hotelQuarterUploads = mbHotelQuarterUploadMapper.selectByExample(uploadDetailExample);
        HotelQuarterUploadPageResponseVo pageResponseVo = new HotelQuarterUploadPageResponseVo();
        PageInfo pageInfo = new PageInfo<>(hotelQuarterUploads);
        Page<HotelQuarterUpload> page = new Page(pageInfo.getPageNum(), pageInfo.getPageSize(), pageInfo.getPages(),
                pageInfo.getTotal(), hotelQuarterUploads);
        List<HotelQuarterUploadInfoResponseVo> responseVos = new ArrayList<>();
        page.getList().stream().filter(Objects::nonNull).forEach(item -> {
            HotelQuarterUploadInfoResponseVo responseVo = new HotelQuarterUploadInfoResponseVo();
            responseVo.setCreateTime(DateUtil.dateToString(item.getCreateTime(), DateUtil.DF_YMD_HMS));
            responseVo.setFailNumber(item.getFailNumber());
            responseVo.setFileName(item.getFileName());
            responseVo.setUploadNumber(item.getUploadNumber());
            responseVo.setOperatorName(item.getOperatorName());
            responseVo.setSuccessNumber(item.getSuccessNumber());
            responseVo.setStatus(item.getStatus());
            responseVo.setUploadId(item.getId());
            responseVo.setTsHotelName(item.getTsHotelName());
            responseVos.add(responseVo);
        });
        pageResponseVo.setUploadDetailResponseVos(responseVos);//返回前端结果
        pageResponseVo.setCurrentPage(requestVo.getPageNum());
        pageResponseVo.setPageSize(requestVo.getPageSize());
        pageResponseVo.setTotalCount(Integer.parseInt(pageInfo.getTotal() + ""));
        pageResponseVo.setTotalPage(page.getTotalPage());
        return pageResponseVo;
    }

    public HotelQuarterUploadDetailPageResponseVo selectQuarterUploadDetailInfoPage(HotelQuarterUploadDetailPageRequestVo requestVo) {
        PageHelper.startPage(requestVo.getPageNum(), requestVo.getPageSize());
        Example uploadDetailExample = new Example(HotelQuarterUploadDetail.class);
        uploadDetailExample.createCriteria().andEqualTo("uploadId", requestVo.getUploadId())
                .andEqualTo("status", QuarterImportExcelDeatilStatusEnum.F.getDealCode());
        List<HotelQuarterUploadDetail> hotelQuarterUploadDetails =
                mbHotelQuarterDetailUploadMapper.selectByExample(uploadDetailExample);
        HotelQuarterUploadDetailPageResponseVo pageResponseVo = new HotelQuarterUploadDetailPageResponseVo();
        PageInfo pageInfo = new PageInfo<>(hotelQuarterUploadDetails);
        Page<HotelQuarterUploadDetail> page = new Page(pageInfo.getPageNum(), pageInfo.getPageSize(),
                pageInfo.getPages(), pageInfo.getTotal(), hotelQuarterUploadDetails);
        List<HotelQuarterUploadDetailResponseVo> responseVos = new ArrayList<>();
        page.getList().stream().filter(Objects::nonNull).forEach(item -> {
            HotelQuarterUploadDetailResponseVo responseVo = new HotelQuarterUploadDetailResponseVo();
            responseVo.setLine(item.getLine());
            responseVo.setFiledReason(item.getFailedReason());
            responseVo.setStatus(item.getStatus());
            responseVos.add(responseVo);
        });
        pageResponseVo.setUploadDetailResponseVos(responseVos);//返回前端结果
        pageResponseVo.setCurrentPage(requestVo.getPageNum());
        pageResponseVo.setPageSize(requestVo.getPageSize());
        pageResponseVo.setTotalCount(Integer.parseInt(pageInfo.getTotal() + ""));
        pageResponseVo.setTotalPage(page.getTotalPage());
        return pageResponseVo;
    }
    public void downloadHotelQuarter(MbTravelstandHotelQuarterVo quarterVo, HttpServletResponse response) {
        if (quarterVo.getTsHotelId() == null) {
            throw new CorpBusinessException(OrganizationResponseCodeEnum.HOTEL_TRAVEL_STANDARD_ERROR);
        }
        MbTravelstandHotel mbTravelstandHotel = mbTravelstandHotelMapper.selectByPrimaryKey(quarterVo.getTsHotelId());
        if (mbTravelstandHotel == null) {
            throw new CorpBusinessException(OrganizationResponseCodeEnum.HOTEL_TRAVEL_STANDARD_ERROR);
        }
        if (HotelSwitchEnum.QuarterSwitch.N.getCode().equals(mbTravelstandHotel.getQuarterSwitch())) {
            throw new CorpBusinessException(OrganizationResponseCodeEnum.PLEASE_ENABLE_QUARTER_SWITCH);
        }
        List<HotelQuarterDownloadResponseVo> responseVos = new ArrayList<>();
        quarterVo.setHotelType(AreaTypeEnum.HOTEL_TYPE_0.getCode());
        quarterVo.setPageSize(200);
        List<MbTravelstandHotelQuarterVo> quarterList = ListUtils.copyList(mbTravelstandHotelQuarterMapper.listByQuarterVo(quarterVo),MbTravelstandHotelQuarterVo.class);
        if (CollectionUtils.isNotEmpty(quarterList)) {
            Map<Long, List<MbTravelstandHotelQuarterVo>> collect =
                    quarterList.stream().collect(Collectors.groupingBy(MbTravelstandHotelQuarterVo::getTsHotelAreaId));
            List<HotelQuarterDownloadResponseVo> domesticOtherCityList = new ArrayList<>();
            List<HotelQuarterDownloadResponseVo> otherAreaInfo = new ArrayList<>();
            for (Map.Entry<Long, List<MbTravelstandHotelQuarterVo>> entry : collect.entrySet()) {
                MbTravelstandHotelQuarterVo hotelQuarterVo = entry.getValue().get(0);
                if (!AreaTypeEnum.TYPE_0.getCode().equals(hotelQuarterVo.getAreaType())) {
                    if (AreaTypeEnum.HOTEL_TYPE_0.getCode().equals(hotelQuarterVo.getHotelType())) {
                        otherAreaInfo = convertQuarterExcelVo(entry.getValue());
                    }
                } else {
                    domesticOtherCityList.addAll(convertQuarterExcelVo(entry.getValue()));
                }
            }
            domesticOtherCityList.addAll(otherAreaInfo);
            responseVos.addAll(domesticOtherCityList);
        }
        responseVos.stream().forEach(quarter -> {
            if (StringUtils.isBlank(quarter.getPriceUpperLimit())) {
                quarter.setPriceUpperLimit("不限");
            }
        });
        SecureRandom random = new SecureRandom();
        StringBuilder fileName = new StringBuilder("淡旺季差标导出数据").append(DateUtil.dateToString(new Date(),
                DateUtil.DFYMD)).append(random.nextInt(900000) + 100000);
        ExcelPostEnum excelPostEnum = ExcelPostEnum.xlsx;
        String sheetName = mbTravelstandHotel.getName();
        sheetName = sheetName.replaceAll("/", "-");
        ExcelCreateVO<HotelQuarterDownloadResponseVo> vo = ExcelCreateVO.<HotelQuarterDownloadResponseVo>builder()
                .fileName(fileName.toString())
                .dataList(responseVos)
                .postfix(excelPostEnum)
                .cls(HotelQuarterDownloadResponseVo.class)
                .sheetName(sheetName)
                .build();
        excelUtils.downloadExcelDocument(response, vo);
    }

    public JSONResult downloadQuarterTemplate(String orgId, HttpServletResponse response) {
        try {
            String fileName = FileTemplateEnum.SyncHotelQuarterTemplate.getDealMsg();
            InputStream inputStream = ExcelUtils.class.getClassLoader().getResourceAsStream(String.format(
                    "syncorgexceltemplate/%s", fileName));
            XSSFWorkbook workBook = new XSSFWorkbook(inputStream);
            XSSFSheet sheet = workBook.getSheetAt(0);
            //塞入所有国内城市名称
            AreaConfigVo areaConfigVo = new AreaConfigVo();
            areaConfigVo.setOrgId(orgId);
            areaConfigVo.setHotelType(AreaTypeEnum.HOTEL_TYPE_0.getCode());
            areaConfigVo.setStatus(0);
            List<AreaConfigVo> areaConfigVoList = areaConfigService.list(areaConfigVo);
            List<AreaConfigVo> areaConfigResult = new ArrayList<>();
            AreaConfigVo otherDomesticCity = null;
            for (AreaConfigVo configVo : areaConfigVoList) {
                if (AreaTypeEnum.TYPE_0.getCode().equals(configVo.getAreaType())) {
                    areaConfigResult.add(configVo);
                } else {
                    otherDomesticCity = configVo;
                }
            }
            if (otherDomesticCity != null) {
                areaConfigResult.add(otherDomesticCity);
            }
            if (CollectionUtils.isNotEmpty(areaConfigResult)) {
                int size = areaConfigResult.size();
                sheet.shiftRows(2, 2 + size, size, true, false);
                for (int i = 0; i < size; i++) {
                    XSSFRow creRow = sheet.createRow(2 + i);
                    creRow.createCell(0).setCellValue(areaConfigResult.get(i).getAreaName());
                }
            }
            //浏览器下载
            response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE);
            response.setHeader("Content-Disposition", "attachment;filename=" + fileName);
            response.flushBuffer();
            workBook.write(response.getOutputStream());
            inputStream.close();
        } catch (IOException e) {
            log.error("下载模板异常", e);
            return JSONResult.errorMsg("下载模板异常");
        }
        return JSONResult.success(null);
    }

    @Transactional(rollbackFor = Exception.class)
    public JSONResult syncHotelQuarterExcel(MultipartFile file, MbTravelstandHotelQuarterVo requestVo) {
        if (file == null) {
            throw new CorpBusinessException(ExceptionCodeEnum.Alert, "上传文件为空");
        }
        if (!file.getOriginalFilename().endsWith(".xls") && !file.getOriginalFilename().endsWith(".xlsx")) {
            throw new CorpBusinessException(ExceptionCodeEnum.Alert, "文件格式必须为xls或xlsx");
        }
        if (Objects.isNull(requestVo.getTsHotelId())) {
            throw new CorpBusinessException(OrganizationResponseCodeEnum.HOTEL_TRAVEL_STANDARD_ERROR);
        }
        MbTravelstandHotel mbTravelstandHotel = mbTravelstandHotelMapper.selectByPrimaryKey(requestVo.getTsHotelId());
        if (mbTravelstandHotel == null) {
            throw new CorpBusinessException(OrganizationResponseCodeEnum.HOTEL_TRAVEL_STANDARD_ERROR);
        }
        Workbook workbook = null;

        try {
            if (file.getOriginalFilename().endsWith(".xls")) {
                workbook = new HSSFWorkbook(file.getInputStream());
            } else if (file.getOriginalFilename().endsWith(".xlsx")) {
                workbook = new XSSFWorkbook(file.getInputStream());
            }
        } catch (IOException e) {
            log.error("上传淡旺季异常:{}", e.getMessage());
            return JSONResult.errorMsg("电子表格格式错误，请重新导入！");
        }

        // 取出第一页
        Sheet sheet = workbook.getSheetAt(0);
        //校验模板
        checkQuarterTemplate(sheet);
        // Excel内容
        List<HotelQuarterColumnVo> beanListFromExcel =
                excelUtils.getBeanListFromExcelTwo(sheet, HotelQuarterColumnVo.class);

        // 剔除空格
        beanListFromExcel.forEach(StrUtils::fieldRemoveWarp);

        if (CollectionUtils.isEmpty(beanListFromExcel)) {
            throw new CorpBusinessException(OrganizationResponseCodeEnum.HOTEL_TRAVEL_QUARTER_EMPTY);
        }
        try {
            //查询当前租户所有地区信息
            AreaConfigVo areaConfigVo = new AreaConfigVo();
            areaConfigVo.setOrgId(mbTravelstandHotel.getOrgId());
            areaConfigVo.setHotelType(AreaTypeEnum.HOTEL_TYPE_0.getCode());
            areaConfigVo.setStatus(0);
            List<AreaConfigVo> areaConfigVoList = areaConfigService.list(areaConfigVo);
            Map<String, Long> areaMap = areaConfigVoList.stream().collect(Collectors.toMap(AreaConfigVo::getAreaName,
                    AreaConfigVo::getId, (k1, k2) -> k2));
            // 校验数据
            HotelQuarterUploadExcelInfo uploadExcelInfo =
                    this.checkExcelInfo(beanListFromExcel, mbTravelstandHotel, areaMap);
            // 组织数据
            QuarterInfoExcelSaveBo assembleInfo =
                    this.assembleInfo(uploadExcelInfo, requestVo, file.getOriginalFilename(), mbTravelstandHotel,
                            areaMap);


            HotelQuarterUpload hotelQuarterUpload = assembleInfo.getHotelQuarterUpload();
            if (Objects.nonNull(hotelQuarterUpload.getFailNumber()) && hotelQuarterUpload.getFailNumber() > 0) {
                hotelQuarterUpload.setStatus(QuarterImportExcelRecordStatusEnum.F.getDealCode());
                mbHotelQuarterUploadMapper.updateByPrimaryKeySelective(hotelQuarterUpload);
                List<HotelQuarterUploadDetail> hotelQuarterUploadDetails = assembleInfo.getHotelQuarterUploadDetails();
                if (CollectionUtils.isNotEmpty(hotelQuarterUploadDetails)) {
                    hotelQuarterUploadDetails.forEach(r -> r.setUploadId(hotelQuarterUpload.getId()));
                    mbHotelQuarterDetailUploadMapper.insertList(hotelQuarterUploadDetails);
                }
                return JSONResult.ok();
            }

            //启用时导入会删除所有历史淡旺季
            Long tsId = mbTravelstandHotel.getId();
            if (HotelSwitchEnum.QuarterSwitch.N.getCode().equals(mbTravelstandHotel.getQuarterSwitch())) {
                mbTravelstandHotelQuarterMapper.deleteByTsId(tsId);
                Set<Long> needAddDefaultQuarterAreas = assembleInfo.getNeedAddDefaultQuarterAreas();
                List<MbTravelstandHotelQuarter> quarterList = new ArrayList<>();
                if (CollectionUtils.isNotEmpty(needAddDefaultQuarterAreas)) {
                    Date date = new Date();
                    for (Long needAddDefaultQuarter : needAddDefaultQuarterAreas) {
                        MbTravelstandHotelQuarter quarter = new MbTravelstandHotelQuarter();
                        quarter.setTsHotelId(tsId);
                        quarter.setTsHotelAreaId(needAddDefaultQuarter);
                        quarter.setDatachangeCreatetime(date);
                        quarter.setDatachangeLasttime(date);
                        quarterList.add(quarter);
                    }
                    mbTravelstandHotelQuarterMapper.insertList(quarterList);
                }


            }
            if (CollectionUtils.isNotEmpty(assembleInfo.getInsertQuarterList())) {
                Date date = new Date();
                //tkmapper insertList好像不支持数据库默认字段
                assembleInfo.getInsertQuarterList().forEach(r -> {
                    r.setDatachangeCreatetime(date);
                    r.setDatachangeLasttime(date);
                });
                mbTravelstandHotelQuarterMapper.insertList(assembleInfo.getInsertQuarterList());
            }
            if (CollectionUtils.isNotEmpty(assembleInfo.getUpdateQuarterList())) {
                Date date = new Date();
                for (MbTravelstandHotelQuarter hotelQuarter : assembleInfo.getUpdateQuarterList()) {
                    hotelQuarter.setDatachangeLasttime(date);
                    mbTravelstandHotelQuarterMapper.updateQuarter(hotelQuarter);
                }
            }
            //如果淡旺季关闭，则开启
            if (CollectionUtils.isNotEmpty(assembleInfo.getInsertQuarterList()) || CollectionUtils.isNotEmpty(assembleInfo.getUpdateQuarterList()) && HotelSwitchEnum.QuarterSwitch.N.getCode().equals(mbTravelstandHotel.getQuarterSwitch())) {
                mbTravelstandHotel.setQuarterSwitch(HotelSwitchEnum.QuarterSwitch.E.getCode());
                mbTravelstandHotelMapper.updateByPrimaryKey(mbTravelstandHotel);
            }
            // 上传记录表更新
            if (Objects.nonNull(hotelQuarterUpload.getFailNumber()) && hotelQuarterUpload.getFailNumber() > 0) {
                hotelQuarterUpload.setStatus(QuarterImportExcelRecordStatusEnum.F.getDealCode());
            } else {
                hotelQuarterUpload.setStatus(QuarterImportExcelRecordStatusEnum.E.getDealCode());

            }
            mbHotelQuarterUploadMapper.updateByPrimaryKeySelective(hotelQuarterUpload);
            List<HotelQuarterUploadDetail> hotelQuarterUploadDetails = assembleInfo.getHotelQuarterUploadDetails();
            if (CollectionUtils.isNotEmpty(hotelQuarterUploadDetails)) {
                hotelQuarterUploadDetails.forEach(r -> r.setUploadId(hotelQuarterUpload.getId()));
                mbHotelQuarterDetailUploadMapper.insertList(hotelQuarterUploadDetails);
            }
        } catch (Exception e) {
            log.error("上传酒店差标淡旺季异常:", e);
            return JSONResult.errorMsg(e.getMessage());
        }
        return JSONResult.ok();
    }

    public QuarterInfoExcelSaveBo assembleInfo(HotelQuarterUploadExcelInfo excelInfo,
                                               MbTravelstandHotelQuarterVo requestVo, String fileName,
                                               MbTravelstandHotel mbTravelstandHotel,
                                               Map<String, Long> areaMap) {
        QuarterInfoExcelSaveBo infoExcelSaveBo = new QuarterInfoExcelSaveBo();
        List<HotelQuarterUploadDetail> hotelQuarterUploadDetails = new ArrayList<>();
        List<MbTravelstandHotelQuarter> insertQuarters = new ArrayList<>();
        List<MbTravelstandHotelQuarter> updateQuarters = new ArrayList<>();
        Integer successNumber = 0;
        Integer failNumber = 0;
        List<HotelQuarterUploadExcelInfo.HotelQuarterUploadDetailBo> allDetailBos = excelInfo.getAllDetailBos();
        List<HotelQuarterUploadExcelInfo.HotelQuarterUploadDetailBo> allUpdateDetailBos =
                excelInfo.getUpdateDetailBos();
        BaseUserInfo baseUserInfo = UserInfoContext.getContextParams(BaseUserInfo.class);
        Set<Long> noNeedAddDefaultQuarterSet = new HashSet<>();
        for (HotelQuarterUploadExcelInfo.HotelQuarterUploadDetailBo uploadInfo : allDetailBos) {
            HotelQuarterUploadDetail quarterUploadDetail = new HotelQuarterUploadDetail();
            quarterUploadDetail.setAreaName(uploadInfo.getHotelAreaName());
            quarterUploadDetail.setBeginDate(uploadInfo.getStartTime());
            quarterUploadDetail.setEndDate(uploadInfo.getEndTime());
            quarterUploadDetail.setPriceUpperLimit(uploadInfo.getPriceUpperLimit());
            quarterUploadDetail.setLine(uploadInfo.getLine());
            quarterUploadDetail.setTsHotelId(requestVo.getTsHotelId());
            quarterUploadDetail.setFailedReason(uploadInfo.getFailedReason());
            hotelQuarterUploadDetails.add(quarterUploadDetail);
            if (StringUtils.isNotBlank(uploadInfo.getFailedReason())) {
                quarterUploadDetail.setStatus(QuarterImportExcelDeatilStatusEnum.F.getDealCode());
                failNumber++;
            } else {
                noNeedAddDefaultQuarterSet.add(uploadInfo.getHotelAreaId());
                quarterUploadDetail.setStatus(QuarterImportExcelDeatilStatusEnum.E.getDealCode());
                MbTravelstandHotelQuarter hotelQuarter = new MbTravelstandHotelQuarter();
                hotelQuarter.setAreaName(uploadInfo.getHotelAreaName());
                hotelQuarter.setTsHotelAreaId(uploadInfo.getHotelAreaId());
                hotelQuarter.setTsHotelId(uploadInfo.getTsHotelId());
                if (uploadInfo.getPriceUpperLimit() != null && NumberUtils.isParsable(uploadInfo.getPriceUpperLimit())) {
                    hotelQuarter.setPriceUpperLimit(new BigDecimal(uploadInfo.getPriceUpperLimit()));
                }
                if (StringUtils.isBlank(uploadInfo.getStartTime()) || StringUtils.isBlank(uploadInfo.getEndTime()) ) {
                    continue;
                }
                hotelQuarter.setStartTime(uploadInfo.getStartTime());
                hotelQuarter.setEndTime(uploadInfo.getEndTime());
                if (allUpdateDetailBos.contains(uploadInfo)) {
                    hotelQuarter.setId(uploadInfo.getId());
                    updateQuarters.add(hotelQuarter);
                } else {
                    insertQuarters.add(hotelQuarter);
                }
                successNumber++;
            }
        }
        //现存的所有地区配置
        Collection<Long> dbAreaIdList = areaMap.values();
        //除了表里要加的，其他的淡旺季需要加个默认的淡旺季控制
        Set<Long> needAddDefaultQuarterAreaSet=
                dbAreaIdList.stream().filter(r -> !noNeedAddDefaultQuarterSet.contains(r)).collect(Collectors.toSet());
        HotelQuarterUpload quarterUpload = new HotelQuarterUpload();
        quarterUpload.setFileName(fileName);
        quarterUpload.setTsHotelName(mbTravelstandHotel.getName());
        quarterUpload.setTsHotelId(mbTravelstandHotel.getId());
        quarterUpload.setOperatorName(baseUserInfo.getUserName());
        quarterUpload.setUploadNumber(allDetailBos.size());
        quarterUpload.setStatus(QuarterImportExcelRecordStatusEnum.U.getDealCode());
        quarterUpload.setOrgId(mbTravelstandHotel.getOrgId());
        mbHotelQuarterUploadMapper.insertSelective(quarterUpload);
        quarterUpload.setSuccessNumber(successNumber);
        quarterUpload.setFailNumber(failNumber);
        infoExcelSaveBo.setHotelQuarterUpload(quarterUpload);
        infoExcelSaveBo.setInsertQuarterList(insertQuarters);
        infoExcelSaveBo.setUpdateQuarterList(updateQuarters);
        infoExcelSaveBo.setHotelQuarterUploadDetails(hotelQuarterUploadDetails);
        infoExcelSaveBo.setNeedAddDefaultQuarterAreas(needAddDefaultQuarterAreaSet);
        return infoExcelSaveBo;
    }

    private void checkQuarterTemplate(Sheet sheet) {
        List<String> headerList = Arrays.asList("*地区名称", "均价上限", "*淡旺季开始日期", "*淡旺季结束日期");
        for (int i = 0; i < headerList.size(); i++) {
            if (!sheet.getRow(1).getCell(i).getStringCellValue().equals(headerList.get(i))) {
                throw new CorpBusinessException(OrganizationResponseCodeEnum.HOTEL_TRAVEL_QUARTER_TEMPLATE_ERROR);
            }
        }
    }
    public Map<String, HotelControlVo> getHotelDetailList(List<GetHotelDetailRequest> requestList) {
        if (CollectionUtils.isEmpty(requestList)){
            return Collections.emptyMap();
        }
        return requestList.stream().map(t -> {
                    HotelControlVo hotelControlVo = getHotelDetail(t);
                    return new Tuple(t.getUid(), hotelControlVo);
        }).collect( HashMap::new,
                (m,node) -> m.put(node.get(0),node.get(1)),
                HashMap::putAll);

    }






    /**
     * 获得酒店差标相关信息
     *
     * @param request
     * @return
     */
    public HotelControlVo getHotelDetail(GetHotelDetailRequest request) {
        log.info("MbTravelstandHotelService.getHotelDetail(), request={}", JsonUtils.toJsonString(request));
        String uid = request.getUid();
        String orgId = request.getOrgId();
        String cityCode = request.getCityCode();
        Long postId = request.getPostId();
        MbTravelstandHotelVo mbTravelstandHotelVo = getMbTravelstandHotelVoByuidAndOrgId(uid, orgId, postId);
        log.info("获取到的差标配置为:{}", JsonUtils.toJsonString(mbTravelstandHotelVo));
        if (StringUtils.isBlank(orgId)){
            orgId = mbTravelstandHotelVo.getOrgId();
        }
        //判断CityCode是城市还是国家 cityCode=cityId 名字有差异
        HotelCityBo hotelCityBo = hotelCityDataService.searchHotelCity(cityCode);
        log.info("MbTravelstandHotelService.getHotelDetail(), hotelCityBo={}", JsonUtils.toJsonString(hotelCityBo));
        if(Objects.isNull(hotelCityBo)) {
            throw new CorpBusinessException(OrganizationResponseCodeEnum.HOTEL_CITY_COUNTRY_IS_NULL);
        }
        if (mbTravelstandHotelVo == null) {
            return null;
        }
        // 确保产线管控开关一定被返回
        HotelControlVo hotelControlVo = new HotelControlVo();
        hotelControlVo.setHotelProductSwitch(mbTravelstandHotelVo.getHotelProductSwitch());
        hotelControlVo.setHotelIntlProductSwitch(mbTravelstandHotelVo.getHotelIntlProductSwitch());
        log.info("确保产线管控开关一定被返回, hotelControlVo:{}", JsonUtils.toJsonString(hotelControlVo));
        if (Objects.equals("CN", hotelCityBo.getCountryCode()) && !Objects.equals(HotelSwitchEnum.priceSwitch.E.getCode(), mbTravelstandHotelVo.getPriceSwitch())) {
            return hotelControlVo;
        }

        if (!Objects.equals("CN", hotelCityBo.getCountryCode()) && !Objects.equals(HotelSwitchEnum.priceSwitch.E.getCode(), mbTravelstandHotelVo.getPriceSwitchIntl())) {
            return hotelControlVo;
        }
        Date startDate = request.getStartDate();
        Date endDate = request.getEndDate();
        String corpId = getCorpIdByOrgId(orgId);
        List<AreaConfigVo> areaConfigVos = areaConfigService.getByOrgIdAndTsIdAndCityCode(corpId, cityCode, mbTravelstandHotelVo.getId());
        log.info("MbTravelstandHotelService.getHotelDetail(), corpid={}, cityCode={}, tsId={}, areaConfigVos={}", corpId, cityCode, mbTravelstandHotelVo.getId(), JsonUtils.toJsonString(areaConfigVos));
        if (CollectionUtils.isEmpty(areaConfigVos) || areaConfigVos.size() > 1) {
            // 区域没有配置，或者找到多条
            return hotelControlVo;
        }
        AreaConfigVo areaConfigVo = areaConfigVos.get(0);
        List<MbTravelstandHotelPriceVo> mbTravelstandHotelPriceVos = travelstandHotelPriceService.list(new MbTravelstandHotelPriceVo() {{
            setTsHotelId(mbTravelstandHotelVo.getId());
            setTsHotelAreaId(areaConfigVo.getId());
        }});
        log.info("MbTravelstandHotelService.getHotelDetail(), TsHotelId={}, TsHotelAreaId={}, mbTravelstandHotelPriceVos={}", mbTravelstandHotelVo.getId(), areaConfigVo.getId(), JsonUtils.toJsonString(mbTravelstandHotelPriceVos));
        if (mbTravelstandHotelPriceVos == null || mbTravelstandHotelPriceVos.size() < 1) {
            return hotelControlVo;
        }
        MbTravelstandHotelPriceVo mbTravelstandHotelPriceVo = mbTravelstandHotelPriceVos.get(0);
        if (mbTravelstandHotelPriceVo == null) {
            return hotelControlVo;
        }
        List<MbTravelstandHotelQuarterVo> mbTravelstandHotelQuarterVoList = travelstandHotelQuarterService.list(
                new MbTravelstandHotelQuarterVo()
                        .setTsHotelAreaId(areaConfigVo.getId())
                        .setTsHotelId(mbTravelstandHotelVo.getId())
        );
        log.info("MbTravelstandHotelService.getHotelDetail(), TsHotelId={}, TsHotelAreaId={}, mbTravelstandHotelQuarterVoList={}", mbTravelstandHotelVo.getId(), areaConfigVo.getId(), JsonUtils.toJsonString(mbTravelstandHotelQuarterVoList));
        //假如地区限价、星级、淡旺季都为null则返回null
        if (mbTravelstandHotelPriceVo.getPriceUpperLimit() == null && mbTravelstandHotelPriceVo.getStar() == null) {
            if (HotelSwitchEnum.QuarterSwitch.N.getCode().equals(mbTravelstandHotelVo.getQuarterSwitch()) || mbTravelstandHotelQuarterVoList == null || mbTravelstandHotelQuarterVoList.size() == 0) {
                return hotelControlVo;
            }
        }
        //设置均价
        AveragePriceSet averagePriceSet = new AveragePriceSet();
        BigDecimal priceUpperLimit = mbTravelstandHotelPriceVo.getPriceUpperLimit();
        String currencyCode = mbTravelstandHotelPriceVo.getCurrencyCode();
        CurrencyExchangeBO exchangeBO = mbTravelstandCurrencyExchangeService.exchangeAmountAndToken(currencyCode, priceUpperLimit);
        log.info("MbTravelstandHotelService.getHotelDetail(), exchangeBO={}", JsonUtils.toJsonString(exchangeBO));
        String exchangeToken = exchangeBO.getExchangeToken();
        BigDecimal priceCeiling = exchangeBO.getToCurrencyAmount();
        averagePriceSet.setOriginalAmount(priceUpperLimit);
        averagePriceSet.setPriceFloor(BigDecimal.ZERO.setScale(0, RoundingMode.HALF_UP).toString());
        averagePriceSet.setExchangeToken(exchangeToken);
        //假如淡旺季开启，则计算公式为：(淡旺季价格*在淡旺季中的天数+地区限价*不在淡旺季中的天数)/总天数=均价上限
        if (HotelSwitchEnum.QuarterSwitch.E.getCode().equals(mbTravelstandHotelVo.getQuarterSwitch()) && startDate!=null && endDate!=null) {
            log.info("MbTravelstandHotelService.getHotelDetail(), startDate={}，endDate={}", startDate, endDate);
            if (!startDate.before(endDate)) {
                throw new CorpBusinessException(OrganizationResponseCodeEnum.DATE_ERROR);
            }
            //计算淡旺季差标价
            priceCeiling = calculateQuarterPrice(areaConfigVo.getId(), mbTravelstandHotelVo.getId(), mbTravelstandHotelPriceVo.getPriceUpperLimit(), startDate, endDate);;
            if(priceCeiling!=null) {
                averagePriceSet.setPriceCeiling(priceCeiling.setScale(0, RoundingMode.HALF_UP).toString());
            }
        } else {
            averagePriceSet.setPriceCeiling(priceCeiling.setScale(0, RoundingMode.HALF_UP).toString());
        }
        log.info("获取当前管控差标数值:{}", JsonUtils.toJsonString(averagePriceSet.getPriceCeiling()));
        averagePriceSet.setCurrencyCode(currencyCode);
        hotelControlVo.setAveragePriceSet(averagePriceSet);
        //设置星级
        Integer star = mbTravelstandHotelPriceVo.getStar();
        if (star != null) {
            AverageStarSet averageStarSet = new AverageStarSet();
            StarFloor starFloor = new StarFloor();
            starFloor.setName("一星级");
            starFloor.setValue("1");
            averageStarSet.setStarFloor(starFloor);
            StarCeiling starCeiling = new StarCeiling();
            starCeiling.setName(STAR_NAMES[star]);
            starCeiling.setValue(String.valueOf(star));
            averageStarSet.setStarCeiling(starCeiling);
            hotelControlVo.setAverageStarSet(averageStarSet);
        }
        //设置管控
        hotelControlVo.setControl(getControl(mbTravelstandHotelVo.getControlType()));
        hotelControlVo.setFloatAveragePriceSet(setFloatAveragePriceSet(mbTravelstandHotelVo, mbTravelstandHotelPriceVo, hotelCityBo, hotelControlVo));
        if (Objects.nonNull(hotelControlVo.getFloatAveragePriceSet())) {
            hotelControlVo.setFloatControl(getControl(mbTravelstandHotelVo.getFloatControlType()));
        }
        log.info("获取到差标配置:{}", JsonUtils.toJsonString(hotelControlVo));
        return hotelControlVo;
    }

    private Integer getControl(String floatControlType) {
        if (ControlTypeEnum.F.getCode().equals(floatControlType)) {
            return NumberUtils.INTEGER_ZERO;
        } else if (ControlTypeEnum.C.getCode().equals(floatControlType)) {
            return NumberUtils.INTEGER_ONE;
        } else if (ControlTypeEnum.A.getCode().equals(floatControlType)) {
            return NumberUtils.INTEGER_TWO;
        } else if (ControlTypeEnum.M.getCode().equals(floatControlType)) {
            return 3;
        } else {
            return 4;
        }
    }

    /**
     *  浮动差标设置
     * @param mbTravelstandHotelVo
     * @param mbTravelstandHotelPriceVo
     * @param hotelCityBo
     * @return
     */
    private AveragePriceSet setFloatAveragePriceSet(MbTravelstandHotelVo mbTravelstandHotelVo, MbTravelstandHotelPriceVo mbTravelstandHotelPriceVo, HotelCityBo hotelCityBo, HotelControlVo hotelControlVo) {
        if (Objects.equals("CN", hotelCityBo.getCountryCode()) && !Objects.equals(HotelSwitchEnum.priceSwitch.E.getCode(), mbTravelstandHotelVo.getPriceFloatSwitch())) {
            return null;
        }

        if (!Objects.equals("CN", hotelCityBo.getCountryCode()) && !Objects.equals(HotelSwitchEnum.priceSwitch.E.getCode(), mbTravelstandHotelVo.getPriceFloatSwitchIntl())) {
            return null;
        }
        if (StringUtils.isEmpty(mbTravelstandHotelPriceVo.getFloatType())) {
            return null;
        }
        AveragePriceSet averagePriceSet = new AveragePriceSet();
        //标准差标价格
        String priceCeiling = hotelControlVo.getAveragePriceSet().getPriceCeiling();
        String currencyCode = hotelControlVo.getAveragePriceSet().getCurrencyCode();
        //如果无法获取限价，则认为不限，将价格设置为最大
        if (Objects.isNull(priceCeiling)){
            averagePriceSet.setPriceCeiling(new BigDecimal(Long.MAX_VALUE).toString());
            return averagePriceSet;
        }
        if (Objects.equals(HotelTravelStanderFloatTypeEnum.PERCENTAGE.getCode(), mbTravelstandHotelPriceVo.getFloatType())) {
            averagePriceSet.setPriceCeiling(new BigDecimal(priceCeiling).add(
                    new BigDecimal(priceCeiling).multiply((
                            Optional.ofNullable(mbTravelstandHotelPriceVo.getFloatPercentage()).orElse(BigDecimal.ZERO)
                            .divide(new BigDecimal(100))))
            ).toString());
        } else {
            BigDecimal floatAmount = mbTravelstandHotelPriceVo.getFloatAmount();
            CurrencyExchangeBO currencyExchangeBO = mbTravelstandCurrencyExchangeService.exchangeAmountAndToken(currencyCode, floatAmount);
            averagePriceSet.setPriceCeiling(new BigDecimal(priceCeiling).add(
                    Optional.ofNullable(currencyExchangeBO.getToCurrencyAmount()).orElse(BigDecimal.ZERO)
            ).toString());
        }
        return averagePriceSet;
    }

    public List<ReasonInfo> getHotelRcInfo(String uid, String orgId, String cityCode) {
        List<ReasonInfo> reasonInfos = new ArrayList<>();
        MbTravelstandHotelVo mbTravelstandHotelVo = getMbTravelstandHotelVoByuidAndOrgId(uid, orgId, null);
        if (mbTravelstandHotelVo == null) {
            return null;
        }
        if (ControlTypeEnum.F.getCode().equals(mbTravelstandHotelVo.getControlType())) {
            return null;
        }
        //价格管控rc
        List<MbTravelstandReasonCodeVo> mbTravelstandReasonCodeVos = travelstandReasonCodeService.list(new MbTravelstandReasonCodeVo() {{
            setTsRcType(ReasonCodeTypeEnum.HP.getCode());
            setTsId(mbTravelstandHotelVo.getId());
            setIsChecked(true);
        }});
        List<HotelRcValue> hotelRcValueList = new ArrayList<>();
        for (MbTravelstandReasonCodeVo mbTravelstandReasonCodeVo : mbTravelstandReasonCodeVos) {
            HotelRcValue hotelRcValue = new HotelRcValue();
            hotelRcValue.setName(mbTravelstandReasonCodeVo.getName());
            hotelRcValue.setValue(mbTravelstandReasonCodeVo.getId().toString());
            hotelRcValueList.add(hotelRcValue);
        }
        Map<String, List<HotelRcValue>> data = new HashMap<>();
        data.put("根据贵公司差旅政策规定，继续预订您需要提供未预订差标内房型的原因:", hotelRcValueList);
        ReasonInfo priceReasonInfo = new ReasonInfo();
        priceReasonInfo.setSelectValue(data);
        //设置reasonInfos
        reasonInfos.add(priceReasonInfo);
        return reasonInfos;
    }

    public ExecuteHotelTravelStandardSoaResponse executeHotelTravelStandardSoa(ExecuteHotelTravelStandardRequest request) {
        String uid = request.getUid();
        String orgId = request.getOrgId();
        MbTravelstandHotelVo mbTravelstandHotelVo = getMbTravelstandHotelVoByuidAndOrgId(uid, orgId, null);
        if (mbTravelstandHotelVo == null) {
            return null;
        }
        orgId = getCorpIdByOrgId(orgId);
        ExecuteHotelTravelStandardSoaResponse executeHotelTravelStandardSoaResponse = new ExecuteHotelTravelStandardSoaResponse();
        String cityCode = request.getCityCode();
        Date checkInTime = request.getCheckInTime();
        Date checkOutDate = request.getCheckOutTime();
        executeHotelTravelStandardSoaResponse.setSharedManageStatus(mbTravelstandHotelVo.getSharedManageStatus());
        //判断CityCode是城市还是国家 cityCode=cityId 名字有差异
        HotelCityBo hotelCityBo = hotelCityDataService.searchHotelCity(cityCode);
        if (Objects.isNull(hotelCityBo)) {
            throw new CorpBusinessException(OrganizationResponseCodeEnum.HOTEL_CITY_COUNTRY_IS_NULL);
        }
        Boolean isOpenSwitch;
        if (Objects.equals("CN", hotelCityBo.getCountryCode())) {
            isOpenSwitch = Objects.equals(HotelSwitchEnum.priceSwitch.E.getCode(), mbTravelstandHotelVo.getPriceSwitch());
        } else {
            isOpenSwitch = Objects.equals(HotelSwitchEnum.priceSwitch.E.getCode(), mbTravelstandHotelVo.getPriceSwitchIntl());
        }

        //设置价格管控
        if (isOpenSwitch) {
            List<AreaConfigVo> areaConfigVos = areaConfigService.getByOrgIdAndTsIdAndCityCode(orgId, cityCode, mbTravelstandHotelVo.getId());
            List<ExecuteHotelTravelStandardSoaResponse.Info> infos = new ArrayList<>();
            for (AreaConfigVo areaConfigVo : areaConfigVos) {
                MbTravelstandHotelPriceVo mbTravelstandHotelPriceVo = travelstandHotelPriceService.selectOne(new MbTravelstandHotelPriceVo() {{
                    setTsHotelAreaId(areaConfigVo.getId());
                    setTsHotelId(mbTravelstandHotelVo.getId());
                }});
                ExecuteHotelTravelStandardSoaResponse.Info info = new ExecuteHotelTravelStandardSoaResponse.Info();
                if (mbTravelstandHotelPriceVo != null) {
                    info.setStar(mbTravelstandHotelPriceVo.getStar() == null ? null : mbTravelstandHotelPriceVo.getStar().toString());
                    info.setAreaName(mbTravelstandHotelPriceVo.getAreaName());
                    if (mbTravelstandHotelPriceVo.getPriceUpperLimit() != null) {
                        info.setAreaPrice(mbTravelstandHotelPriceVo.getPriceUpperLimit().setScale(0, RoundingMode.HALF_UP).toString());
                    }
                    if (Objects.nonNull(mbTravelstandHotelPriceVo.getCurrencyCode())){
                        info.setCurrencyCode(mbTravelstandHotelPriceVo.getCurrencyCode());
                    }
                }
                if (HotelSwitchEnum.QuarterSwitch.E.getCode().equals(mbTravelstandHotelVo.getQuarterSwitch())) {
                    BigDecimal quarterPrice = calculateQuarterPrice(areaConfigVo.getId(), mbTravelstandHotelVo.getId(), mbTravelstandHotelPriceVo.getPriceUpperLimit(),checkInTime, checkOutDate);
                    if(quarterPrice!=null) {
                        info.setAreaPrice(quarterPrice.toString());
                    }
                }
                infos.add(info);
            }
            executeHotelTravelStandardSoaResponse.setInfos(infos);
            //设置价格管控rc
            if (ControlTypeEnum.C.getCode().equals(mbTravelstandHotelVo.getControlType())) {
                List<MbTravelstandReasonCodeVo> mbTravelstandReasonCodeVos = travelstandReasonCodeService.list(new MbTravelstandReasonCodeVo().setTsId(mbTravelstandHotelVo.getId()).setTsRcType(ReasonCodeTypeEnum.HP.getCode()));
                List<String> rcs = new ArrayList<>();
                for (MbTravelstandReasonCodeVo mbTravelstandReasonCodeVo : mbTravelstandReasonCodeVos) {
                    rcs.add(mbTravelstandReasonCodeVo.getName());
                }
                executeHotelTravelStandardSoaResponse.setControlRcInfos(rcs);
            }
        }
        return executeHotelTravelStandardSoaResponse;
    }

    public HotelTravelStandardManageVo getHotelTravelStandard(String uid, String orgId) {
        MbTravelstandHotelVo travelstandHotelVo = getMbTravelstandHotelVoByuidAndOrgId(uid, orgId, null);
        if (travelstandHotelVo == null) {
            return null;
        }
        //获取rc
        List<MbTravelstandReasonCodeVo> reasonCodeVos = travelstandReasonCodeService.list(new MbTravelstandReasonCodeVo() {{
            setTsId(travelstandHotelVo.getId());
            setTsType(TravelStandardTypeEnum.Hotel.getCode());
        }});
        //获取岗位
        List<TravelStandardPost> travelStandardPosts = travelStandardPostService.list(new TravelStandardPostVo() {{
            setTsid(travelstandHotelVo.getId());
            setTstype(TravelStandardTypeEnum.Hotel.getCode());
        }});
        //获取区域限价
        List<MbTravelstandHotelPriceVo> travelstandHotelPriceVos = travelstandHotelPriceService.listAllTravelstandHotelPrice(travelstandHotelVo.getId(), travelstandHotelVo.getOrgId());
        //获取淡旺季信息
        List<MbTravelstandHotelQuarterVo> travelstandHotelQuarterVos = travelstandHotelQuarterService.list(
                new MbTravelstandHotelQuarterVo().setTsHotelId(travelstandHotelVo.getId())
        );
        return BeanConverUtil.travelstandHotelVoToHotelTravelStandardManageVo(
                travelstandHotelVo,
                ListUtils.copyList(travelStandardPosts, TravelStandardPostVo.class),
                reasonCodeVos,
                travelstandHotelPriceVos,
                travelstandHotelQuarterVos
        );
    }

    /**
     * 根据uid和orgId获得对应酒店差标
     *
     * @param uid
     * @param orgId 组织id，对应的组织类型可能是公司、部门。
     *              用于从mb_user_org_relation表中拿到对应的职级id
     * @return
     */
    public MbTravelstandHotelVo getMbTravelstandHotelVoByuidAndOrgId(String uid, String orgId, Long postId) {
        log.info("getMbTravelstandHotelVoByuidAndOrgId,uid:{},orgId:{},postId:{}",uid,orgId,postId);
        if (Objects.nonNull(postId) && postId > 0){

        }else{
            if (StringUtils.isBlank(uid)) {
                throw new CorpBusinessException(OrganizationResponseCodeEnum.UID_NULL);
            }
            if (StringUtils.isBlank(orgId)) {
                throw new CorpBusinessException(OrganizationResponseCodeEnum.ORG_ID_NULL);
            }
            //根据uid和orgId查到对应职位
            PostVo postVo = postService.listPostByUidAndOrgId(uid, orgId);
            log.info("根据uid和orgId查到对应职位,postVo:{}", JsonUtils.toJsonString(postVo));
            //判断岗位是否存在
            if (postVo == null) {
                return null;
            }
            postId = postVo.getId();
        }

        //根据职位查找对应酒店差标
        TravelStandardPostVo vo = new TravelStandardPostVo();
        vo.setPostid(postId);
        vo.setTstype(TravelStandardTypeEnum.Hotel.getCode());
        List<TravelStandardPost> travelStandardPostVos = travelStandardPostService.list(vo);
        log.info("根据职位查找对应酒店差标,vo:{},travelStandardPostVos:{}",JsonUtils.toJsonString(vo),JsonUtils.toJsonString(travelStandardPostVos));
        if (travelStandardPostVos == null || travelStandardPostVos.size() == 0) {
            return null;
        }
        TravelStandardPost travelStandardPost = travelStandardPostVos.get(0);
        //获取对应差标
        Long tsId = travelStandardPost.getTsid();
        MbTravelstandHotelVo mbTravelstandHotelVo = get(tsId);
        if (mbTravelstandHotelVo == null) {
            return null;
        }
        log.info("return mbTravelstandHotelVo:{}",JsonUtils.toJsonString(mbTravelstandHotelVo));
        return mbTravelstandHotelVo;
    }

    /**
     * 将MbTravelstandHotelVo转换为HotelOperateLogVo
     */
    private HotelOperateLogVo coverMbTravelstandHotelVoToFlightOperateLogVo(MbTravelstandHotelVo mbTravelstandHotelVo) {
        if (mbTravelstandHotelVo != null) {
            HotelOperateLogVo hotelOperateLogVo = new HotelOperateLogVo();
            hotelOperateLogVo.setName(mbTravelstandHotelVo.getName());
            HotelSwitchEnum.priceSwitch priceSwitch = HotelSwitchEnum.priceSwitch.getEnumByCode(mbTravelstandHotelVo.getPriceSwitch());
            hotelOperateLogVo.setPriceSwitch(priceSwitch == null ? "" : priceSwitch.getName());
            ControlTypeEnum controlTypeEnum = ControlTypeEnum.getEnumByCode(mbTravelstandHotelVo.getControlType());
            hotelOperateLogVo.setPriceControlType(controlTypeEnum == null ? "" : controlTypeEnum.getName());
            //设置职级范围
            List<String> jobNames = travelStandardPostService.getJobNamesByTsIdAndTsType(mbTravelstandHotelVo.getId(), TravelStandardTypeEnum.Hotel.getCode());
            StringBuilder jobScope = new StringBuilder();
            for (String jobName : jobNames) {
                jobScope.append(jobName);
                jobScope.append(",");
            }
            if (jobNames.size() > 0) {
                jobScope.deleteCharAt(jobScope.length() - 1);
            }
            hotelOperateLogVo.setJobScope(jobScope.toString());
            //设置地区限价信息
            StringBuilder priceInfo = new StringBuilder();
            if (HotelSwitchEnum.priceSwitch.E.getCode().equals(mbTravelstandHotelVo.getPriceSwitch())) {
                List<MbTravelstandHotelPriceVo> mbTravelstandHotelPriceVos = travelstandHotelPriceService.list(new MbTravelstandHotelPriceVo() {{
                    setTsHotelId(mbTravelstandHotelVo.getId());
                }});
                for (MbTravelstandHotelPriceVo mbTravelstandHotelPriceVo : mbTravelstandHotelPriceVos) {
                    priceInfo.append(mbTravelstandHotelPriceVo.getAreaName());
                    priceInfo.append("：");
                    if (mbTravelstandHotelPriceVo.getPriceUpperLimit() != null) {
                        priceInfo.append(mbTravelstandHotelPriceVo.getPriceUpperLimit().setScale(2, RoundingMode.HALF_UP).toString());
                    } else {
                        priceInfo.append("无上限");
                    }
                    priceInfo.append(",");
                }
                if (mbTravelstandHotelPriceVos.size() > 0) {
                    priceInfo.deleteCharAt(priceInfo.length() - 1);
                }
            }
            hotelOperateLogVo.setPriceInfo(priceInfo.toString());
            //限价超标管控原因
            if (ControlTypeEnum.C.getCode().equals(mbTravelstandHotelVo.getControlType())) {
                List<MbTravelstandReasonCodeVo> mbTravelstandReasonCodeVos = travelstandReasonCodeService.list(new MbTravelstandReasonCodeVo() {{
                    setTsId(mbTravelstandHotelVo.getId());
                    setTsRcType(ReasonCodeTypeEnum.HP.getCode());
                }});
                StringBuilder priceControlRcs = new StringBuilder();
                for (MbTravelstandReasonCodeVo codeVo : mbTravelstandReasonCodeVos) {
                    priceControlRcs.append(codeVo.getName());
                    priceControlRcs.append(",");
                }
                if (mbTravelstandReasonCodeVos.size() > 0) {
                    priceControlRcs.deleteCharAt(priceControlRcs.length() - 1);
                }
                hotelOperateLogVo.setPriceControlRcs(priceControlRcs.toString());
            }
            return hotelOperateLogVo;
        }
        return null;
    }

    /**
     * 传入的orgId不确定为部门id或者公司id，这里通过组织架构接口，传入组织id，如果该组织是公司，则返回该id，如果不是，则返回最近的公司id
     * <p>
     * 酒店的地区信息是挂在公司下面的，而不是部门下面，查差标需要用到部门id，而查地区信息则需要公司id，故需要转换
     */
    private String getCorpIdByOrgId(String orgId) {
		MbOrgInfo orgInfoVo = organizationInfoService.findRecentCompanyIdByOrgId(orgId);
		if (orgInfoVo != null) {
            return orgInfoVo.getOrgId();
        }
        return null;
    }

    @Override
    public MbTravelstandHotelVo getHotelSwitch(String uid, String orgId) {
        return getMbTravelstandHotelVoByuidAndOrgId(uid, orgId, null);
    }

    private void productControlConvert(List<HotelForAppVo> hotelForAppVos){
        HotelForAppVo hotelForAppVo = new HotelForAppVo();
        ArrayList<RcDetailVo> rcDetailVos = new ArrayList<>();
        RcDetailVo rcDetailVo = new RcDetailVo();
        rcDetailVo.setTitle("产线管控");
        rcDetailVo.setContent("禁止预订");
        rcDetailVos.add(rcDetailVo);
        hotelForAppVo.setRcDetail(rcDetailVos);
        hotelForAppVos.add(hotelForAppVo);
    }

    /**
     * 计算淡旺季差标价
     * @param areaId
     * @param tsId
     * @param checkInTime
     * @param checkOutDate
     */
    public BigDecimal calculateQuarterPrice(Long areaId, Long tsId, BigDecimal price, Date checkInTime, Date checkOutDate){
        List<MbTravelstandHotelQuarterVo> mbTravelstandHotelQuarterVoList = travelstandHotelQuarterService.list(new MbTravelstandHotelQuarterVo().setTsHotelAreaId(areaId).setTsHotelId(tsId));
        if(CollectionUtils.isEmpty(mbTravelstandHotelQuarterVoList)){
            return price;
        }
        Date date = checkInTime==null?new Date():checkInTime;
        Date endDate = checkOutDate==null?DateUtils.addDate(date, Calendar.DATE, 1):checkOutDate;
        BigDecimal total = BigDecimal.ZERO;
        int count = 0;
        int size = 0;
        // 最多循环1000次
        while (date.before(endDate) && size++<1000) {
            BigDecimal datePrice = price;
            for (MbTravelstandHotelQuarterVo mbTravelstandHotelQuarterVo : mbTravelstandHotelQuarterVoList) {
                log.info("淡旺季计算：date={}, beginDate={}, endDate={},price={}", DateUtils.format(date, DATE_FORMAT),
                        DateUtils.format(mbTravelstandHotelQuarterVo.getBeginDate(), DATE_FORMAT),
                        DateUtils.format(mbTravelstandHotelQuarterVo.getEndDate(), DATE_FORMAT), price);
                if (mbTravelstandHotelQuarterVo.getBeginDate() == null || mbTravelstandHotelQuarterVo.getEndDate() == null) {
                    continue;
                }
                if (compareDate(date, mbTravelstandHotelQuarterVo.getBeginDate())>=0
                        && compareDate(date, mbTravelstandHotelQuarterVo.getEndDate())<=0
                        && mbTravelstandHotelQuarterVo.getPriceUpperLimit() != null) {
                    datePrice = mbTravelstandHotelQuarterVo.getPriceUpperLimit();
                    log.info("淡旺季计算命中：date={}, beginDate={}, endDate={}, price={}", DateUtils.format(date, DATE_FORMAT),
                            DateUtils.format(mbTravelstandHotelQuarterVo.getBeginDate(), DATE_FORMAT),
                            DateUtils.format(mbTravelstandHotelQuarterVo.getEndDate(), DATE_FORMAT), price);
                }
            }
            if(datePrice!=null) {
                total = total.add(datePrice);
                ++count;
            }
            date = DateUtils.addDate(date, Calendar.DATE, 1);
        }
        if(count>0) {
            return total.divide(new BigDecimal(count), 2, BigDecimal.ROUND_HALF_UP);
        }
        return price;
    }

    /**
     * 日期比较，精确到天
     * @param date1
     * @param date2
     * @return
     */
    private int compareDate(Date date1, Date date2){
        String d1 = DateUtils.format(date1, DateUtils.DATE_FORMAT);
        String d2 = DateUtils.format(date2, DateUtils.DATE_FORMAT);
        return d1.compareTo(d2);
    }
}
